OK, here’s an example how delete_at(index)
would have simplified and quickened the initial design to solve this task.
Here’s the short version for the task, which takes about 164 seconds for outputs.
def palindromicgapfuls(digit, count)
gapfuls = [] of UInt64 # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
palindrome = 0_u64 # init for compiler
(2..).select do |power|
base = 10_u64**(power >> 1) # value of middle digit position: 10..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
num_half = front_half.to_s # d_n0
(front_half..front_half + 9).each_with_index do |upper_half, i|
palindrome = (upper_half.to_s + upper_half.to_s.reverse).to_u64 if power.odd?
palindrome = (num_half.rchop + num_half.reverse).to_u64 + base * i if power.even?
gapfuls << palindrome if palindrome % nn == 0
return gapfuls if gapfuls.size == count
end
end
end
end
Here’s @asterite’s functional hack for delete_at
, which took 660 seconds.
def palindromicgapfuls(digit, count)
gapfuls = [] of UInt64 # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
mid = (power >> 1) + 1 # mid index of righthand side
base = 10_u64**(power >> 1) # value of middle digit position: 10..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
(front_half..front_half + 9).each do |upper_half|
palindrome = (upper_half.to_s + upper_half.to_s.reverse).to_u64
palindrome = (palindrome.to_s[0..mid-2] + palindrome.to_s[mid..-1]).to_u64 if power.even?
gapfuls << palindrome if palindrome % nn == 0
return gapfuls if gapfuls.size == count
end
end
end
end
It’s shorter, and if you don’t care about speed, it’s the easiest conceptual way to do it.
Now here’s how simple it would be using delete_at
.
def palindromicgapfuls(digit, count)
gapfuls = [] of UInt64 # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
mid = (power >> 1) + 1 # mid index of righthand side
base = 10_u64**(power >> 1) # value of middle digit position: 10..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.step(to: next_lo - 1, by: 10) do |front_half| # d_00; d_10; d_20; ...
(front_half..front_half + 9).each do |upper_half|
palindrome = (upper_half.to_s + upper_half.to_s.reverse).to_u64
palindrome = (palindrome.to_s.delete_at(mid-1)).to_u64 if power.even?
gapfuls << palindrome if palindrome % nn == 0
return gapfuls if gapfuls.size == count
end
end
end
end
Now it’s even more conceptually clear what’s going on.
If you’re doing any kind of text processing, this stuff is done all the time.
Surprisingly, even Ruby doesn’t have an equivalent method to do exactly this.
Addition:
This is even more concise and efficient, and much faster, only ~340 seconds vs 660.
def palindromicgapfuls(digit, count)
gapfuls = [] of UInt64 # array of palindromic gapfuls
nn = digit * 11 # digit gapful divisor: 11, 22,...88, 99
(2..).select do |power|
mid = (power >> 1) + 1 # mid index of righthand side
base = 10_u64**(power >> 1) # value of middle digit position: 10..
this_lo = base * digit # starting half for this digit: 10.. to 90..
next_lo = base * (digit + 1) # starting half for next digit: 20.. to 100..
this_lo.upto(next_lo - 1) do |left_half|
palindrome = left_half.to_s + left_half.to_s.reverse
palindrome = (palindrome[0..mid-2] + palindrome[mid..-1]) if power.even?
palindrome = palindrome.to_u64
gapfuls << palindrome if palindrome % nn == 0
return gapfuls if gapfuls.size == count
end
end
end