From: tamouse mailing lists Date: 2013-05-31T11:20:23+09:00 Subject: Re: Eloquent Ruby Kaprekar's Number On Thu, May 30, 2013 at 9:08 PM, tamouse mailing lists wrote: > On Thu, May 30, 2013 at 6:59 PM, Alphonse 23 wrote: >> Which way is the eloquent ruby way to write this algorithm? >> >> Kaprekar Number >> >> 9 is a Kaprekar number since >> 9 ^ 2 = 81 and 8 + 1 = 9 >> >> 297 is also Kaprekar number since >> 297 ^ 2 = 88209 and 88 + 209 = 297. >> >> In short, for a Kaprekar number k with n-digits, if you square it and >> add the right n digits to the left n or n-1 digits, the resultant sum is >> k. >> >> !Spoiler Below! >> >> # way one >> def kaprekar?(k) >> ks = k**2 >> lenf = (ks.to_s.length)-1 >> lenh = (ks.to_s.length / 2) - 1 >> a = ks.to_s[0..lenh].to_i >> b = ks.to_s[lenh+1..lenf].to_i >> k == (a+b) >> end >> >> # way two >> def kaprekar?(k) >> a = (k**2).to_s[0..((((k**2).to_s.length) / 2) - 1)].to_i >> b = (k**2).to_s[(((((k**2).to_s.length) / 2) - >> 1)+1)..(((k**2).to_s.length)-1)].to_i >> k == (a+b) >> end >> >> # way three >> def kaprekar?(k) >> k == ((k**2).to_s[0..((((k**2).to_s.length) / 2) - >> 1)].to_i)+((k**2).to_s[(((((k**2).to_s.length) / 2) - >> 1)+1)..(((k**2).to_s.length)-1)].to_i) >> end >> >> def simple_test(i) >> if kaprekar?(i) == true then p "success on #{i}" else "fail on #{i}" >> end >> end >> >> simple_test(9) >> simple_test(297) >> >> All three pass my tests, but which of the three would be considered the >> most eloquent written ruby way? As in, which would be consider best >> style-wise? The first takes up the most lines, but uses less nesting. >> The last uses only one line but uses lots of nesting. >> >> -- >> Posted via http://www.ruby-forum.com/. >> > > This is the way I'd do it: > > def kaprekar?(k) > > n = k.to_s.length > ks = (k*k).to_s > l = ((n-1)-(n%2)) > l = 0 if l < 0 > > nl = ks[0..l].to_i > nr = ks[-n..-1].to_i > > k == nl + nr > > end > > > I could not say if that's more rubyist or not, though. I imagine there > is probably a way to use map/reduce and pass a block or something ;) > Well, that will teach me not to test more thoroughly. def kaprekar?(k) n = k.to_s.length ks = (k*k).to_s l = ((n-1)-(ks.length%2)) l = 0 if l < 0 nl = ks[0..l].to_i nr = ks[-n..-1].to_i if k == nl + nr puts "k=#{k}, n=#{n}, ks=#{ks}, l=#{l}, nl=#{nl}, nr=#{nr}, nl+nr=#{nl+nr}" true else false end end and some tests: irb(main):056:0> 0.upto(1000).each {|i| puts "#{i} is kaprekar" if kaprekar?(i)} k=0, n=1, ks=0, l=0, nl=0, nr=0, nl+nr=0 0 is kaprekar k=9, n=1, ks=81, l=0, nl=8, nr=1, nl+nr=9 9 is kaprekar k=45, n=2, ks=2025, l=1, nl=20, nr=25, nl+nr=45 45 is kaprekar k=55, n=2, ks=3025, l=1, nl=30, nr=25, nl+nr=55 55 is kaprekar k=99, n=2, ks=9801, l=1, nl=98, nr=1, nl+nr=99 99 is kaprekar k=297, n=3, ks=88209, l=1, nl=88, nr=209, nl+nr=297 297 is kaprekar k=703, n=3, ks=494209, l=2, nl=494, nr=209, nl+nr=703 703 is kaprekar k=999, n=3, ks=998001, l=2, nl=998, nr=1, nl+nr=999 999 is kaprekar