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

Discussion in 'Ruby' started by Matthew Moss, Sep 20, 2008.

  1. Matthew Moss

    Matthew Moss Guest

    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    The three rules of Ruby Quiz 2:

    1. This week only -- no waiting period!

    2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
    permanent, new website is in the works for Ruby Quiz 2. Until then,
    please visit the temporary website at

    <http://splatbang.com/rubyquiz/>.

    3. Enjoy!

    Suggestion: A [QUIZ] in the subject of emails about the problem
    helps everyone on Ruby Talk follow the discussion. Please reply to
    the original quiz message, if you can.

    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    Apologies for being late today... 'twas distracted by my English
    report!

    ## One-Liners Mashup (#177)

    This week is going to be very informal, and without any particular
    task or submission. It's hunting season, and we're hunting one-liners.

    Basically, we'll start with the simple problem I've presented below.
    Your solution must fit in one line. (Golfing is okay, but not
    necessary. One line *generally* means about 80 chars wide, but we're
    flexible here.) If you are writing a method, the `def foo(args)` and
    `end` (and `class Whatever` and `end` for adding methods to a class)
    doesn't count... the body of the method will.

    Of course, your solutions should be generally useful, and not hard-
    coded to solve any particular example used to illustrate what the
    solution should do.

    Post your solution AND a followup problem for others to solve. Repeat
    ad nauseum (or until about Wed/Thu).

    Ready? Here goes. First problem...
    You should know this pattern well:

    > [:eek:ne, "two", 4] * 3

    => [:eek:ne, "two", 4, :eek:ne, "two", 4, :eek:ne, "two", 4]

    Write a single line method on Array that does this instead:

    > [:eek:ne, "two", 4].repeat(3)

    => [:eek:ne, :eek:ne, :eek:ne, "two", "two", "two", 4, 4, 4]
    Matthew Moss, Sep 20, 2008
    #1
    1. Advertising

  2. Matthew Moss

    Matthew Moss Guest

    Re: One-Liners Mashup (#177 again)

    And if it wasn't clear from the very top... no no-spoiler period this
    week.
    Matthew Moss, Sep 20, 2008
    #2
    1. Advertising

  3. Matthew Moss

    Daniel Moore Guest

    def repeat(i)
    r = []; each { |x| r.push(*([x] * i)) }; r
    end

    Challenge:
    Print out a Serpinski carpet.

    On Fri, Sep 19, 2008 at 4:43 PM, Matthew Moss <> wrote:
    > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    >
    > The three rules of Ruby Quiz 2:
    >
    > 1. This week only -- no waiting period!
    >
    > 2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
    > permanent, new website is in the works for Ruby Quiz 2. Until then,
    > please visit the temporary website at
    >
    > <http://splatbang.com/rubyquiz/>.
    >
    > 3. Enjoy!
    >
    > Suggestion: A [QUIZ] in the subject of emails about the problem
    > helps everyone on Ruby Talk follow the discussion. Please reply to
    > the original quiz message, if you can.
    >
    > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    >
    > Apologies for being late today... 'twas distracted by my English
    > report!
    >
    > ## One-Liners Mashup (#177)
    >
    > This week is going to be very informal, and without any particular
    > task or submission. It's hunting season, and we're hunting one-liners.
    >
    > Basically, we'll start with the simple problem I've presented below.
    > Your solution must fit in one line. (Golfing is okay, but not
    > necessary. One line *generally* means about 80 chars wide, but we're
    > flexible here.) If you are writing a method, the `def foo(args)` and
    > `end` (and `class Whatever` and `end` for adding methods to a class)
    > doesn't count... the body of the method will.
    >
    > Of course, your solutions should be generally useful, and not hard-
    > coded to solve any particular example used to illustrate what the
    > solution should do.
    >
    > Post your solution AND a followup problem for others to solve. Repeat
    > ad nauseum (or until about Wed/Thu).
    >
    > Ready? Here goes. First problem...
    > You should know this pattern well:
    >
    > > [:eek:ne, "two", 4] * 3

    > => [:eek:ne, "two", 4, :eek:ne, "two", 4, :eek:ne, "two", 4]
    >
    > Write a single line method on Array that does this instead:
    >
    > > [:eek:ne, "two", 4].repeat(3)

    > => [:eek:ne, :eek:ne, :eek:ne, "two", "two", "two", 4, 4, 4]
    >
    >
    >




    --
    -Daniel
    http://strd6.com
    Daniel Moore, Sep 20, 2008
    #3
  4. On Fri, Sep 19, 2008 at 9:21 PM, Daniel Moore <> wrote:
    > def repeat(i)
    > r = []; each { |x| r.push(*([x] * i)) }; r
    > end
    >

    Here's mine:
    def repeat(i)
    self.map {|x| [x] * i}.flatten
    end

    I don't appreciate Ruby syntax enough to understand the significance
    of the *(...) construct in Daniel's solution. What does that do? Can
    you show an example where the results are different than my solution?

    --wpd
    Patrick Doyle, Sep 20, 2008
    #4
  5. Matthew Moss

    James Gray Guest

    On Sep 19, 2008, at 6:43 PM, Matthew Moss wrote:

    > First problem...
    > You should know this pattern well:
    >
    >> [:eek:ne, "two", 4] * 3

    > => [:eek:ne, "two", 4, :eek:ne, "two", 4, :eek:ne, "two", 4]
    >
    > Write a single line method on Array that does this instead:
    >
    >> [:eek:ne, "two", 4].repeat(3)

    > => [:eek:ne, :eek:ne, :eek:ne, "two", "two", "two", 4, 4, 4]


    class Array; def repeat(n) zip(*([self] * (n - 1))).flatten end end

    > Post your solution AND a followup problem for others to solve.


    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[x][y] # => 7

    James Edward Gray II
    James Gray, Sep 20, 2008
    #5
  6. > 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[x][y] # => 7
    >

    How about

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

    >> Post your solution AND a followup problem for others to solve.

    Oops, I'll have to think about that... but not tonight

    ... on a completely different topic... I've noticed that whenever I
    post a message to from my gmail account, I get
    the message twice in my inbox, making me wonder three things...
    1) Does everybody get my messages twice? If so, I humbly apologize
    and will stop posting immediately as I can see where this could be
    just a tiny little bit annoying.
    2) Does anybody else have this problem? If so
    3) How did you solve it (assuming it's a solvable problem)?

    --wpd
    Patrick Doyle, Sep 20, 2008
    #6
  7. Matthew Moss

    Daniel Moore Guest

    It splats an array into it's components:
    http://theplana.wordpress.com/2007/03/03/ruby-idioms-the-splat-operator/
    I couldn't use flatten because it would destroy nested arrays.

    [[1,2],[3,4]].repeat(2) => [1, 2, 1, 2, 3, 4, 3, 4] #With flatten

    [[1,2],[3,4]].repeat(2) => [[1, 2], [1, 2], [3, 4], [3, 4]] #Without flatten

    On Fri, Sep 19, 2008 at 6:53 PM, Patrick Doyle <> wrote:
    > On Fri, Sep 19, 2008 at 9:21 PM, Daniel Moore <> wrote:
    >> def repeat(i)
    >> r = []; each { |x| r.push(*([x] * i)) }; r
    >> end
    >>

    > Here's mine:
    > def repeat(i)
    > self.map {|x| [x] * i}.flatten
    > end
    >
    > I don't appreciate Ruby syntax enough to understand the significance
    > of the *(...) construct in Daniel's solution. What does that do? Can
    > you show an example where the results are different than my solution?
    >
    > --wpd
    >
    >




    --
    -Daniel
    http://strd6.com
    Daniel Moore, Sep 20, 2008
    #7
  8. Matthew Moss

    Bill Kelly Guest

    From: "Matthew Moss" <>
    >
    > Ready? Here goes. First problem...
    > You should know this pattern well:
    >
    > > [:eek:ne, "two", 4] * 3

    > => [:eek:ne, "two", 4, :eek:ne, "two", 4, :eek:ne, "two", 4]
    >
    > Write a single line method on Array that does this instead:
    >
    > > [:eek:ne, "two", 4].repeat(3)

    > => [:eek:ne, :eek:ne, :eek:ne, "two", "two", "two", 4, 4, 4]



    # SOLUTION 1:
    # Partial solution, we would need a flatten(1) to prevent it from
    # messing up nested arrays like [:eek:ne, "two", [3]] -- since flatten
    # unarrays recursively.

    class Array; def repeat(n); ([self]*n).transpose.flatten; end; end


    # SOLUTION 2:
    # Avoids flatten, so won't break nested arrays:

    class Array; def repeat(n); ([self]*n).transpose.inject([]){|a,e| a += e}; end; end



    --------------
    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.)



    Regards,

    Bill
    Bill Kelly, Sep 20, 2008
    #8
  9. 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[x][y] # => 7
    > >

    > How about
    >
    > def [](i)
    > @data.map {|row| row}
    > 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][x]}}.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.

    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
    David Masover, Sep 20, 2008
    #9
  10. Matthew Moss

    James Gray Guest

    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[x][y] # => 7
    >>>

    >> How about
    >>
    >> def [](i)
    >> @data.map {|row| row}
    >> 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][x]}}.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.


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

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

    James Edward Gray II
    James Gray, Sep 20, 2008
    #10
  11. Matthew Moss

    James Gray Guest

    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.

    James Edward Gray II
    James Gray, Sep 20, 2008
    #11
  12. James Gray wrote:
    > New puzzle: =A0Provide a one-liner that can wrap a body of text at a =A0
    > 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 8=
    0=20
    characters).

    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.

    =2D-=20
    Jabber:
    ICQ: 205544826
    Sebastian Hungerecker, Sep 20, 2008
    #12
  13. Matthew Moss

    Holger Mack Guest

    [Note: parts of this message were removed to make it a legal post.]

    2008/9/20 Sebastian Hungerecker <>

    > 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.
    >



    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 ;-)

    ----------------------
    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
    Holger Mack, Sep 20, 2008
    #13
  14. Matthew Moss

    Bill Kelly Guest

    From: "Sebastian Hungerecker" <>
    >
    > 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. :)


    > 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
    Bill Kelly, Sep 20, 2008
    #14
  15. Matthew Moss

    Bill Kelly Guest

    From: "Bill Kelly" <>
    > From: "Sebastian Hungerecker" <>
    >
    >> 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
    Bill Kelly, Sep 20, 2008
    #15
  16. Matthew Moss

    Matthew Moss Guest

    Re: One-Liners Mashup (#177 again)


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


    I think you're going to have to explain what periodicity is, or
    provide a link... I've no clue.
    Matthew Moss, Sep 20, 2008
    #16
  17. Matthew Moss

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    >
    > Ready? Here goes. First problem...
    > You should know this pattern well:
    >
    > > [:eek:ne, "two", 4] * 3

    > => [:eek:ne, "two", 4, :eek:ne, "two", 4, :eek:ne, "two", 4]
    >
    > Write a single line method on Array that does this instead:
    >
    > > [:eek:ne, "two", 4].repeat(3)

    > => [:eek:ne, :eek:ne, :eek:ne, "two", "two", "two", 4, 4, 4]




    module Enumerable
    def repeat(n = 1)
    map { |e| [e] * n }.inject { |a,b| a + b }
    end
    end
    James Coglan, Sep 20, 2008
    #17
  18. Matthew Moss

    Matthew Moss Guest

    Re: One-Liners Mashup (#177 again)


    > I didn't really have a problem in mind, but here's an easy one: Write an =

    []=3D
    > method to solve the following:
    >
    > obj =3D YourClass.new
    > obj['answer'] =3D 42
    > obj.answer =A0# =3D> 42



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

    class YourClass
    def []=3D(f, v)
    class << self; self end.instance_eval{ attr_accessor f };
    instance_eval "@#{f}=3Dv"
    end
    end
    Matthew Moss, Sep 20, 2008
    #18
  19. Matthew Moss

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    >
    > 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
    James Coglan, Sep 20, 2008
    #19
  20. Matthew Moss

    Matthew Moss Guest

    Re: One-Liners Mashup (#177 again)


    > I'm no metaprogramming wizard... I keep trying variations until it
    > works. =A0:D =A0This seems to work.
    >
    > class YourClass
    > =A0 def []=3D(f, v)
    > =A0 =A0 class << self; self end.instance_eval{ attr_accessor f };
    > instance_eval "@#{f}=3Dv"
    > =A0 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|####
    Matthew Moss, Sep 20, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ruby Quiz

    [QUIZ] One-Liners (#113)

    Ruby Quiz, Feb 9, 2007, in forum: Ruby
    Replies:
    33
    Views:
    326
    Robert Dober
    Feb 14, 2007
  2. Bruno Michel

    [QUIZ] #113 One-liners

    Bruno Michel, Feb 13, 2007, in forum: Ruby
    Replies:
    0
    Views:
    98
    Bruno Michel
    Feb 13, 2007
  3. Matthew Moss

    [QUIZ] Statistician III (#177)

    Matthew Moss, Sep 13, 2008, in forum: Ruby
    Replies:
    1
    Views:
    107
    Matthew Moss
    Sep 17, 2008
  4. Matthew Moss

    [SUMMARY] One-Liners Mashup (#177)

    Matthew Moss, Sep 26, 2008, in forum: Ruby
    Replies:
    5
    Views:
    137
    Sebastian Hungerecker
    Sep 26, 2008
  5. Larry
    Replies:
    1
    Views:
    99
    Martien Verbruggen
    Feb 3, 2005
Loading...

Share This Page