Rare numbers: Difference between revisions
Content added Content deleted
(→Turbo: Stack corruption bug now fixed.) |
|||
Line 4,226: | Line 4,226: | ||
8th rare number is: 872,568,754,178 |
8th rare number is: 872,568,754,178 |
||
</pre> |
</pre> |
||
=={{header|Ruby}}== |
|||
{{trans|Kotlin}} |
|||
Not sure where, but there seems to be a bug that introduces false rare numbers as output beyond what is shown |
|||
<lang ruby>Term = Struct.new(:coeff, :ix1, :ix2) do |
|||
end |
|||
MAX_DIGITS = 16 |
|||
def toLong(digits, reverse) |
|||
sum = 0 |
|||
if reverse then |
|||
i = digits.length - 1 |
|||
while i >=0 |
|||
sum = sum *10 + digits[i] |
|||
i = i - 1 |
|||
end |
|||
else |
|||
i = 0 |
|||
while i < digits.length |
|||
sum = sum * 10 + digits[i] |
|||
i = i + 1 |
|||
end |
|||
end |
|||
return sum |
|||
end |
|||
def isSquare(n) |
|||
root = Math.sqrt(n).to_i |
|||
return root * root == n |
|||
end |
|||
def seq(from, to, step) |
|||
res = [] |
|||
i = from |
|||
while i <= to |
|||
res << i |
|||
i = i + step |
|||
end |
|||
return res |
|||
end |
|||
def format_number(number) |
|||
number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse |
|||
end |
|||
def main |
|||
pow = 1 |
|||
allTerms = [] |
|||
for i in 0 .. MAX_DIGITS - 2 |
|||
allTerms << [] |
|||
end |
|||
for r in 2 .. MAX_DIGITS |
|||
terms = [] |
|||
pow = pow * 10 |
|||
pow1 = pow |
|||
pow2 = 1 |
|||
i1 = 0 |
|||
i2 = r - 1 |
|||
while i1 < i2 |
|||
terms << Term.new(pow1 - pow2, i1, i2) |
|||
pow1 = (pow1 / 10).to_i |
|||
pow2 = pow2 * 10 |
|||
i1 = i1 + 1 |
|||
i2 = i2 - 1 |
|||
end |
|||
allTerms[r - 2] = terms |
|||
end |
|||
# map of first minus last digits for 'n' to pairs giving this value |
|||
fml = { |
|||
0 =>[[2, 2], [8, 8]], |
|||
1 =>[[6, 5], [8, 7]], |
|||
4 =>[[4, 0]], |
|||
6 =>[[6, 0], [8, 2]] |
|||
} |
|||
# map of other digit differences for 'n' to pairs giving this value |
|||
dmd = {} |
|||
for i in 0 .. 99 |
|||
a = [(i / 10).to_i, (i % 10)] |
|||
d = a[0] - a[1] |
|||
if dmd.include?(d) then |
|||
dmd[d] << a |
|||
else |
|||
dmd[d] = [a] |
|||
end |
|||
end |
|||
fl = [0, 1, 4, 6] |
|||
dl = seq(-9, 9, 1) # all differences |
|||
zl = [0] # zero differences only |
|||
el = seq(-8, 8, 2) # even differences |
|||
ol = seq(-9, 9, 2) # odd differences only |
|||
il = seq(0, 9, 1) |
|||
rares = [] |
|||
lists = [] |
|||
for i in 0 .. 3 |
|||
lists << [] |
|||
end |
|||
fl.each_with_index { |f, i| |
|||
lists[i] = [[f]] |
|||
} |
|||
digits = [] |
|||
count = 0 |
|||
# Recursive closure to generate (n+r) candidates from (n-r) candidates |
|||
# and hence find Rare numbers with a given number of digits. |
|||
fnpr = lambda { |cand, di, dis, indices, nmr, nd, level| |
|||
if level == dis.length then |
|||
digits[indices[0][0]] = fml[cand[0]][di[0]][0] |
|||
digits[indices[0][1]] = fml[cand[0]][di[0]][1] |
|||
le = di.length |
|||
if nd % 2 == 1 then |
|||
le = le - 1 |
|||
digits[(nd / 2).to_i] = di[le] |
|||
end |
|||
di[1 .. le - 1].each_with_index { |d, i| |
|||
digits[indices[i + 1][0]] = dmd[cand[i + 1]][d][0] |
|||
digits[indices[i + 1][1]] = dmd[cand[i + 1]][d][1] |
|||
} |
|||
r = toLong(digits, true) |
|||
npr = nmr + 2 * r |
|||
if not isSquare(npr) then |
|||
return |
|||
end |
|||
count = count + 1 |
|||
print " R/N %2d:" % [count] |
|||
n = toLong(digits, false) |
|||
print " (%s)\n" % [format_number(n)] |
|||
rares << n |
|||
else |
|||
for num in dis[level] |
|||
di[level] = num |
|||
fnpr.call(cand, di, dis, indices, nmr, nd, level + 1) |
|||
end |
|||
end |
|||
} |
|||
# Recursive closure to generate (n-r) candidates with a given number of digits. |
|||
fnmr = lambda { |cand, list, indices, nd, level| |
|||
if level == list.length then |
|||
nmr = 0 |
|||
nmr2 = 0 |
|||
allTerms[nd - 2].each_with_index { |t, i| |
|||
if cand[i] >= 0 then |
|||
nmr = nmr + t.coeff * cand[i] |
|||
else |
|||
nmr2 = nmr2 = t.coeff * -cand[i] |
|||
if nmr >= nmr2 then |
|||
nmr = nmr - nmr2 |
|||
nmr2 = 0 |
|||
else |
|||
nmr2 = nmr2 - nmr |
|||
nmr = 0 |
|||
end |
|||
end |
|||
} |
|||
if nmr2 >= nmr then |
|||
return |
|||
end |
|||
nmr = nmr - nmr2 |
|||
if not isSquare(nmr) then |
|||
return |
|||
end |
|||
dis = [] |
|||
dis << seq(0, fml[cand[0]].length - 1, 1) |
|||
for i in 1 .. cand.length - 1 |
|||
dis << seq(0, dmd[cand[i]].length - 1, 1) |
|||
end |
|||
if nd % 2 == 1 then |
|||
dis << il.dup |
|||
end |
|||
di = [] |
|||
for i in 0 .. dis.length - 1 |
|||
di << 0 |
|||
end |
|||
fnpr.call(cand, di, dis, indices, nmr, nd, 0) |
|||
else |
|||
for num in list[level] |
|||
cand[level] = num |
|||
fnmr.call(cand, list, indices, nd, level + 1) |
|||
end |
|||
end |
|||
} |
|||
#for nd in 2 .. MAX_DIGITS - 1 |
|||
for nd in 2 .. 10 |
|||
digits = [] |
|||
for i in 0 .. nd - 1 |
|||
digits << 0 |
|||
end |
|||
if nd == 4 then |
|||
lists[0] << zl.dup |
|||
lists[1] << ol.dup |
|||
lists[2] << el.dup |
|||
lists[3] << ol.dup |
|||
elsif allTerms[nd - 2].length > lists[0].length then |
|||
for i in 0 .. 3 |
|||
lists[i] << dl.dup |
|||
end |
|||
end |
|||
indices = [] |
|||
for t in allTerms[nd - 2] |
|||
indices << [t.ix1, t.ix2] |
|||
end |
|||
for list in lists |
|||
cand = [] |
|||
for i in 0 .. list.length - 1 |
|||
cand << 0 |
|||
end |
|||
fnmr.call(cand, list, indices, nd, 0) |
|||
end |
|||
print " %2d digits\n" % [nd] |
|||
end |
|||
rares.sort() |
|||
print "\nThe rare numbers with up to %d digits are:\n" % [MAX_DIGITS] |
|||
rares.each_with_index { |rare, i| |
|||
print " %2d: %25s\n" % [i + 1, format_number(rare)] |
|||
} |
|||
end |
|||
main()</lang> |
|||
{{out}} |
|||
<pre> R/N 1: (65) |
|||
2 digits |
|||
3 digits |
|||
4 digits |
|||
5 digits |
|||
R/N 2: (621,770) |
|||
6 digits |
|||
7 digits |
|||
8 digits |
|||
R/N 3: (281,089,082) |
|||
9 digits |
|||
R/N 4: (2,022,652,202) |
|||
R/N 5: (2,042,832,002) |
|||
10 digits |
|||
The rare numbers with up to 16 digits are: |
|||
1: 65 |
|||
2: 621,770 |
|||
3: 281,089,082 |
|||
4: 2,022,652,202 |
|||
5: 2,042,832,002</pre> |
|||
=={{header|Visual Basic .NET}}== |
=={{header|Visual Basic .NET}}== |