Daniel Martin <martin / snowplow.org> writes: > "Suraj N. Kurapati" <skurapat / ucsc.edu> writes: > >> Daniel Martin wrote: >>> I'm a little bit surprised at the paucity of solutions based around >>> sprintf-format strings. >> >> Same here. So far I have seen only two solutions, including mine, >> which use sprintf-format strings. > > So here's one more addition to the sprintf-formatted solution pool: And because I felt like tweaking it a bit more, here's a variation that shows off some more ruby-specific features, like singleton objects and the coerce method that numeric types use. Following how the "g" object in the pp_pascal method works is an exercise in some of ruby's more unique features. (uncommenting the two "p" lines may help) Now, who's going to write up some benchmarking code to test the speed of all these solutions? Also, how do we test them for correctness? I suppose we could test that the last row of output contains the right values, but I don't know how to test whether the output "looks right" in any automated fashion. #!ruby # solution to quiz 84 require 'enumerator' # lnnb stands for "ln of n-bang" # value is from Stirling's approximation def lnnb(n) return 0 if n <= 1 n*Math.log(n) - n + Math.log(2*n*Math::PI)/2 + 1/(12*n) - 1/(360*n*n*n); end # how many digits in the largest number in row "n" # where the rows get counted from 0 def npasdig(n) return 1 if (n < 5) nh = n/2 ((lnnb(n)-lnnb(nh)-lnnb(n-nh))/Math.log(10)).ceil end def pp_pascal(n) width = npasdig(n-1) fmt = "%0s" + "%-#{width}s" * (2*n-2) + "%1s" g = Object.new class << g def coerce(o); 0.coerce(o); end def +(o); o; end def to_s; ""; end def inspect; "g"; end end row = [g]*(2*n+1) row[n] = 1 # p fmt while true do # p row puts(fmt % row) return if row[1] == 1 row = row.enum_cons(3).map{|a,b,c|a+c} row = [g] + row + [g] end end if __FILE__ == $0 n = 4 n = ARGV[0].to_i if ARGV[0] pp_pascal(n) end __END__ My sig needs work; it's nowhere as obfuscated as my perl version... -- "er,acky hRuber oth anustJ".split(/(...)/).reverse.display