[QUIZ] One-Liners Mashup (#177 again)

Shorter carpet solution, still not very nice:

def carpet(n)
  n==0?"#\n":carpet(n-1).map{|l| ['\0\0\0','\0 \0','\0\0\0'].map{|c|
l.gsub(/#| /,c)}}.join
end

puts carpet(2)

next quiz:

Given a text from STDIN and a regexp, print each line which (in part)
matches regexp with two preceding and two successional lines. Do not output
a line more than once.

Regards
Holger

···

2008/9/20 Matthew Moss <matthew.moss@gmail.com>

> Challenge:
> Print out a Serpinski carpet.

Here ya go. Non-negative parameter to the function is recursion depth,
so should be 0 for the "null 1x1 carpet", 1 for the 3x3, 2 for the
9x9, etc. This is golfed, and probably a bit more than 80 chars
(gonna wrap in email, I bet).

def carpet(n)
def k(s,x,y) (s<=3||k(s/3,x/3,y/3))&&!(x%3==1&&y%3==1)
end;s=3**n;s.times{|y|s.times{|x| print k(s,x,y)?"#":" "};puts}
end

Followup: Make my solution shorter. (There's got to be something nicer
than using `times` twice and `print` once.

Hey, you posed that one already in Ruby Quiz 113

class String; def wrap length
   scan(/.{1,#{length}}\s+/).join(" \n")
end; end

New challange:

Starting with an array, find the first permutation of the elements of
that array that is lexicographically greater than (i.e. sorts after)
the given array.

···

James Gray <james@grayproductions.net> wrote:

On Sep 19, 2008, at 9:32 PM, Bill Kelly wrote:

--------------
NEW CHALLENGE:
--------------

# Given one or more input filenames on the command line, # report
the number of unique IP addresses found in all the
# data.
#
# (For our purposes, an IP address may simply be considered
# four integerers separated by dots, e.g.: 6.54.123.9 )
#
# Optionally, the solution should read stdin if no filenames
# were specified.
#
# Preferably, the solution should be expressed in the form of
# a ruby command-line invocation. (Optional.)

ruby -e 'p ARGF.read.scan(/\d{1,3}(\.\d{1,3}){3}/).uniq.size'

New puzzle: Provide a one-liner that can wrap a body of text at a
requested maximum length.

--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

And what about
def prog_sum(array)
  sum = 0; array.collect { |e| sum+=e }
end

···

On Monday 22 September 2008 23:26:34 Martin DeMello wrote:

On Mon, Sep 22, 2008 at 2:07 PM, Matthew Moss <matthew.moss@gmail.com> wrote:
> Too many solvers not providing additional problems!
>
> Here's another... Assuming you have an array of numeric data, write a
> method that returns an array of progressive sums. That is:
>
> prog_sum( [1, 5, 13, -6, 20] ) => [1, 6, 19, 13, 33]

def prog_sum(ary)
  ary.inject([0, ]) {|(s, a), i| [s+i, a<<(s+i)]}.last
end

class Array
  def to_s
    collect{|x| x.to_s.gsub(/\n/,"\n| ")}.join("\n|-- ")
  end
end

puts [:foo, [:bar, [:baz, :quux], :hello, :world], :done].to_s

Works fine for given example but fails for example with
puts [:a, [:b, :c]].to_s

a

-- b
  >-- c

Still working on this...

···

-----------------------------------------------------------------------------
New question

Write a oneliner next_fib(n) which gives the smallest Fibonacci number
greater than n

2008/9/22 Martin DeMello <martindemello@gmail.com>

On Mon, Sep 22, 2008 at 2:07 PM, Matthew Moss <matthew.moss@gmail.com> > wrote:
> Too many solvers not providing additional problems!
>
> Here's another... Assuming you have an array of numeric data, write a
> method that returns an array of progressive sums. That is:
>
> prog_sum( [1, 5, 13, -6, 20] ) => [1, 6, 19, 13, 33]

def prog_sum(ary)
ary.inject([0, ]) {|(s, a), i| [s+i, a<<(s+i)]}.last
end

Followon: Given an s-expression, print it out as a tree, where [:a,
:b, :c, :d] is the node with parent a and children b, c and d

[:foo, [:bar, [:baz, :quux], :hello, :world], :done] #=>

foo
> -- bar
> > -- baz
> > > -- quux
> > -- hello
> > -- world
> -- done

martin

When I wrote the problem, I was thinking of this solution:

class Data2D; def (x) lambda { |y| @data[y] } end

James Edward Gray II

···

On Sep 19, 2008, at 9:34 PM, David Masover wrote:

On Friday 19 September 2008 21:11:21 Patrick Doyle wrote:

Given the class:

class Data2D
  def initialize
    @data = # in row major form
  end

  def add_row(*row)
    @data << row
  end
end

And this setup for an object:

data = Data2D.new
data.add_row(1, 2, 3, 4)
data.add_row(5, 6, 7, 8)

Define a method for the class that makes this form of access possible:

x = 2
y = 1
data[y] # => 7

How about

def (i)
@data.map {|row| row[i]}
end

Curses! You beat me to it, so I wrote a more complex solution:

class Data2D
def (x)
   d=@data; Class.new{ define_method('') {|y| d[y]}}.new
end
end

Counting spaces, it's 64 characters, so it still fits. It has the advantage of
probably being faster on very large datasets, at least for that single
lookup, as no array splicing is done.

class Array; def sortval() sort {|x,y| x.upcase.sum-x.length*64 <=>
y.upcase.sum-y.length*64};end;end

Solution works fine, if array countains only words of only letters. Now I
know, what sum() is for :wink:

···

2008/9/20 Sebastian Hungerecker <sepp2k@googlemail.com>

Next question:
Sort an array of words by the words' values where a word's value is the
sum of the values of its letters and a letter's value is its position in
the alphabet. So the value of "Hello" is 8+5+12+12+15.

----------------------
NEXT QUIZ

Write a function per(n) which returns the periodicity of 1/n, i.e.
  per(3) => 1
  per(4) => 0
  per(7) => 6
  per(11) => 2

Holger

James Gray wrote:
> New puzzle: Provide a one-liner that can wrap a body of text at a > requested maximum length.

Wasn't that a question in the old one liner quiz?
Anyway (without looking it up):
text.gsub(/.{1,80}/,"\\0\n")
Or if you want to avoid breaking in the middle of words:
text.gsub(/(.{1,80})\s+/, "\\1\n")
(you'll have lines above 80 chars if there's a single word with
more than 80 characters).

Indeed, I recall this from a previous ruby-talk thread... my
solution was like your 2nd one, above.... However, I seem to
recall someone had come up with an elegant regexp to actually
wrap words *on-or-before* the boundary.

(I remember being impressed. Wish I could recall the
technique. :slight_smile:

Next question:
Sort an array of words by the words' values where a word's value is the
sum of the values of its letters and a letter's value is its position in
the alphabet. So the value of "Hello" is 8+5+12+12+15.

Here's my solution:

%w(abc abb aba).sort_by{|w| w.upcase.split(//).inject(0){|n,c| n+(c[0] - ?@)} }

=> ["aba", "abb", "abc"]

...I just refereshed my email, and I see that Holger Mack has beat me to a reply. I didn't have a follow-up challenge ready,
so I'll just issue this meta challenge instead:

Look back over the set of one-liner challenges so far which
have gone unanswered and pick one.................

(As of this writing these include, Daniel Moore's "Print out a
Serpinski carpet"; James Gray's "Provide a one-liner that can
wrap a body of text at a requested maximum length." [assuming
strict requirements on maximum length], and, Holger Mack's
"Write a function per(n) which returns the periodicity of 1/n."

Regards,

Bill

···

From: "Sebastian Hungerecker" <sepp2k@googlemail.com>

I didn't really have a problem in mind, but here's an easy one: Write an =
method to solve the following:

obj = YourClass.new
obj['answer'] = 42
obj.answer # => 42

I'm no metaprogramming wizard... I keep trying variations until it
works. :smiley: This seems to work.

class YourClass
  def =(f, v)
    class << self; self end.instance_eval{ attr_accessor f };
instance_eval "@#{f}=v"
  end
end

Ouch, it was. Your memory is better than mine! :slight_smile:

James Edward Gray II

···

On Sep 20, 2008, at 4:07 AM, Sebastian Hungerecker wrote:

James Gray wrote:

New puzzle: Provide a one-liner that can wrap a body of text at a
requested maximum length.

Wasn't that a question in the old one liner quiz?

wrap text with single regexp and strict maximum length

text.gsub(/(.{1,80})\s|(\w{80})/, "\\1\\2\n")

Last one for now, and no followup (we had one for this quiz already)

Regards
Holger

···

2008/9/20 James Coglan <jcoglan@googlemail.com>

>
> New puzzle: Provide a one-liner that can wrap a body of text at a
> requested maximum length.

A first guess... this destroys all original whitespace in the string,
currently trying to fix that.

class String
def line_wrap(n = 80)
   split(/\s+/).inject{ |s,w| s + ("#{s.split("\n").last} #{w}".size > n ?
"\n" : " ") + w }
end
end

Yeah, this was pointed out earlier. I must me losing my mind. Sorry!

James Edward Gray II

···

On Sep 20, 2008, at 10:32 PM, Ken Bloom wrote:

James Gray <james@grayproductions.net> wrote:

On Sep 19, 2008, at 9:32 PM, Bill Kelly wrote:

--------------
NEW CHALLENGE:
--------------

# Given one or more input filenames on the command line, # report
the number of unique IP addresses found in all the
# data.
#
# (For our purposes, an IP address may simply be considered
# four integerers separated by dots, e.g.: 6.54.123.9 )
#
# Optionally, the solution should read stdin if no filenames
# were specified.
#
# Preferably, the solution should be expressed in the form of
# a ruby command-line invocation. (Optional.)

ruby -e 'p ARGF.read.scan(/\d{1,3}(\.\d{1,3}){3}/).uniq.size'

New puzzle: Provide a one-liner that can wrap a body of text at a
requested maximum length.

Hey, you posed that one already in Ruby Quiz 113

New challange:

Starting with an array, find the first permutation of the elements of
that array that is lexicographically greater than (i.e. sorts after)
the given array.

I was tempted to port the C++ next_permutation code, but then I
realized I have class. :frowning:

From: "Sebastian Hungerecker" <sepp2k@googlemail.com>

Or if you want to avoid breaking in the middle of words:
text.gsub(/(.{1,80})\s+/, "\\1\n")
(you'll have lines above 80 chars if there's a single word with
more than 80 characters).

Indeed, I recall this from a previous ruby-talk thread...

Oops - My apologies -- I found the post:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/287353

... and the solution therein appears to have the same single-word
breaking restrictions as Sebastion mentioned above.

Regards,

Bill

···

From: "Bill Kelly" <billk@cts.com>

Write a function per(n) which returns the periodicity of 1/n, i.e.
per(3) => 1
per(4) => 0
per(7) => 6
per(11) => 2

I think you're going to have to explain what periodicity is, or
provide a link... I've no clue.

I'm no metaprogramming wizard... I keep trying variations until it
works. :smiley: This seems to work.

class YourClass
def =(f, v)
class << self; self end.instance_eval{ attr_accessor f };
instance_eval "@#{f}=v"
end
end

Oops... I forgot to put up a new one-liner question! (Don't forget you
guys!!!)

Here's something simple: define method roll(n, s) to roll a s-sided
die n times and display a bar graph of the results. So roll(20, 4)
might look like this:

1|#####
2|#####
3|######
4|####

Nice! That's definitely an improvement over mine.
Also didn't know about for procs.

···

On Friday 19 September 2008 23:27:43 James Gray wrote:

class Data2D; def (x) lambda { |y| @data[y] } end

I've done it, and posted it here, but It's not one line. I'm not sure
if that's even doable.

What I do know is that most permutation generators in Ruby just look
at positions, not data, and by doing so, they yield identical
permutations in a single iteration when there are indentical data
elements.

--Ken

···

Matthew Moss <matthew.moss@gmail.com> wrote:

New challange:

Starting with an array, find the first permutation of the elements of
that array that is lexicographically greater than (i.e. sorts after)
the given array.

I was tempted to port the C++ next_permutation code, but then I
realized I have class. :frowning:

--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Oops... I forgot to put up a new one-liner question! (Don't forget you
guys!!!)

Really sorry, just can't think of anything immediately... if something pops
up I'll post it, promise!

Here's something simple: define method roll(n, s) to roll a s-sided
die n times and display a bar graph of the results. So roll(20, 4)
might look like this:

1|#####
2|#####
3|######
4|####

def roll(n,s)
  (1..n).map { |x| "#{x}|#{'#' * (1 + rand(s))}" } * "\n"
end

puts roll(20,4)

Periodicity of 1/n -> length of the recurring sequence of the decimal
fraction of 1/n
- 1/3 = 0.3333333.... -> "3" -> 1
- 1/7 = 0.1428571428571.... -> "142957" -> 6
- 1/11 = 0.09090909.... -> "09" -> 2

a bonus point: other than decimal fraction

Regards
Holger

···

2008/9/20 Matthew Moss <matthew.moss@gmail.com>

> Write a function per(n) which returns the periodicity of 1/n, i.e.
> per(3) => 1
> per(4) => 0
> per(7) => 6
> per(11) => 2

I think you're going to have to explain what periodicity is, or
provide a link... I've no clue.

I don't think that your method rolls the dice s times.

def roll(n, s)
  a=(1..n).map{|x|"#{x}|"};s.times{a[rand(n)]<<?#};puts a
end

Regards,
Pit

···

2008/9/20 James Coglan <jcoglan@googlemail.com>:

def roll(n,s)
(1..n).map { |x| "#{x}|#{'#' * (1 + rand(s))}" } * "\n"
end

puts roll(20,4)