```#!ruby
=begin

The Quiz was real fun and I spent quite a lot of time on it.  Below
source is rather easy, but believe me I tried lots of different ways
(such as dynamic binary knapsacks etc.), most of them suck because they
need to many method calls.

The code takes about 30 seconds to find all Weird Numbers up to 10_000:

70, 836, 4030, 5830, 7192, 7912, 9272.

The code doesn't scale rather well, the caches would need to be
optimized for that.

=end

class Integer
# 70, 836, 4030, 5830, 7192, 7912, 9272, 10430
def weird?
!has_semiperfect? && !weird2?
end

SEMIPERFECT = {nil => 'shortcut'}

def weird2?(divisors=proper_divisors)
return true  if divisors.any? { |x| SEMIPERFECT[x] }
if brute(self, divisors)
SEMIPERFECT[self] = true
else
false
end
end

SMALL_SEMIPERFECT = [6, 20, 28]    # + [88, 104, 272]

def has_semiperfect?
SMALL_SEMIPERFECT.any? { |v| self % v == 0 }
end

def proper_divisors
d = []
sum = 0
2.upto(Math.sqrt(self)) { |i|
if self % i == 0
d << i << (self / i)
sum += i + (self / i)
end
}

return [nil]  unless sum > self
d << 1
end

def brute(max, values)
values.sort!

values.delete max / 2
max = max / 2

s = values.size
(2**s).downto(0) { |n|
sum = 0
s.times { |i| sum += values[i] * n[i] }
return true  if sum == max
}
false
end
end

if ARGV[0]
n = Integer(ARGV[0])
else
n = 10_000
end

2.step(n, 2) { |i|
p i  if i.weird?
}

__END__
--
Christian Neukirchen  <chneukirchen / gmail.com>  http://chneukirchen.org

```