Hello, world? (#158)

The three rules of Ruby Q. 2:

  1. Please do not post any solutions or spoiler discussion for this
    quiz until 48 hours have passed from the time on this message.

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

    http://matthew.moss.googlepages.com/home.

  3. Enjoy!

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

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

Hello, world?

The first program any new programmer typically sees is one that
prints out “Hello, world!” to the console. This tends to be something
experienced programmers also see when learning a new language. The
first Hello World program was written in B [1] by Kernighan and
looked like this:

     main( ) {
         extrn a, b, c;
         putchar(a); putchar(b); putchar(c); putchar('!*n');
     }

     a 'hell';
     b 'o, w';
     c 'orld';

Most programmers are probably more familiar with the typical C
implementation:

     main() {
         printf("Hello, world!\n");
     }

Ruby can present the same output very simply:

     puts "Hello, world!"

But that’s too simple… I mean, really… anyone can print a
simple string to standard output. Can’t we get more interesting?
Hmmm, how about:

     puts sprintf("%s, %s!", "Hello", "world")

Eh, that looks too much like C. Maybe…

     puts %w(Hello world).join(", ") + "!"

Yeah, that’s definitely looking Ruby-ish.

Your task this week is to print “Hello, world!” to standard output
using Ruby in atypical fashion. Some guildlines:

  • DO submit multiple variants in your submission, but we don’t need
    100 variants from everyone. Try to limit yourself to your best dozen.
  • DO keep things reasonably simple. I would expect many solutions to
    be one- or two-liners, some solutions to involve classes and
    functions, and a variety in-between. But we’re looking for Ruby-isms,
    not volume of code, so don’t write pages upon pages of code just to
    print “Hello, world!”
  • DON’T obfuscate unnecessarily. We’re looking for interesting Ruby
    tricks, not utter confusion. A little obfuscation is okay, but a lot
    is to be avoided.
  • DON’T send me my own examples from above. I already did them. Do
    other stuff. It is okay if your solution is similar to mine,
    provided you make some interesting modifications.

[1] http://cm.bell-labs.com/cm/cs/who/dmr/btut.html

Greetings!

Here’s the result of my quiz solution(s) so far:

$ ruby 158_hello_world.rb
Hello, World!
Hello, World!
Hello, World!
Hello, World!

Regards,

Bill

On Sat, Mar 1, 2008 at 5:54 AM, Bill K. [email protected] wrote:

How did you do that???
Amazing.
R.


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Greetings,

My quiz solution(s) are here:

http://tastyspleen.net/~billk/ruby/quiz/158-hello-world/158_hello_world.rb

I did five Hello World variations. Thus, the output of the program
when run, is simply:

Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

I think I had the most fun with #4, the maze solver:

m = <<MAZE
###±–±–+
^ H| l| o|
#| e| l| |
#±–±±+ |
#| d !*| , |
#| ±-++ -+#
#|l | _ |#
#±-+ ±+ |#
####|r |W|#
##±± -+ |#
##| o |#
##±-±—+#
MAZE

Regards,

Bill

Le 1 mars 2008 à 13:25, Robert D. a écrit :

On Sat, Mar 1, 2008 at 5:54 AM, Bill K. [email protected] wrote:

Greetings!

Here’s the result of my quiz solution(s) so far:

$ ruby 158_hello_world.rb
Hello, World!
Hello, World!
Hello, World!
Hello, World!

How did you do that???
Amazing.

Maybe, but I’d like to see some benchmarks myself…

Fred
}:>

I love the maze !

Can ruby solve it ?

Isn’t that better suited for a pure functional language ?

2008/3/2, Bill K. [email protected]:

On Mar 2, 5:21 pm, “Bill K.” [email protected] wrote:

Hello, World!
Hello, World!
Hello, World!
Hello, World!

Wow. Your solutions are quite creative!

T.

Hi,

From: “Gaspard B.” [email protected]

I love the maze !

Can ruby solve it ?

The code to solve the maze is included in the quiz solution, here:

http://tastyspleen.net/~billk/ruby/quiz/158-hello-world/158_hello_world.rb

See: Variation 4: Ambulatory greeting

Isn’t that better suited for a pure functional language ?

Although I have books on Haskell and Erlang, I have only tinkered
with functional programming so far. However, there is definitely
nothing uncommon about solving mazes in an imperative programming
style.

The algorithm I used in the quiz was a very simplistic, non-recursive
breadcrumb approach.

Regards,

Bill

Here’s 6 little solutions (pastied Parked at Loopia too).
The
last two just print the file name, so they’ll have to be in a “Hello,
world!”
file (or as close as your OS supports).

attempt 1

def print_caller
print caller.first.match(/`(.*)'$/)[1]
end

def H; print_caller; end
def e; print_caller; end
def l; print_caller; end
def o; print_caller; end
def comma; print ‘,’; end
def space; print ’ '; end
def w; print_caller; end
def r; print_caller; end
def d!; print_caller; end
def newline; print “\n”; end

H(); e; l; l; o; comma; space; w; o; r; l; d!; newline

attempt 2

class Hello
def self.printer s; define_method(s) { print s; self }; end
%w{H e l o w r d!}.each { |s| printer(s) }
end

Hello.new.H.e.l.l.o.w.o.r.l.d!

attempt 3

class Hello
def method_missing m; print m; self; end
end

Hello.new.H.e.l.l.o.send(', ').w.o.r.l.d!.send(“\n”)

attempt 4, quine-ish

#!/usr/bin/env ruby

require ‘enumerator’

lines = File.readlines(FILE)
[20, 0,
0, 11,
4, 0,
4, 0,
2, 17,
5, 3,
0, 14,
18, 28,
2, 17,
0, 5,
4, 0,
4, 16,
0, 1,
1, 0].each_slice(2) { |row, col| print lines[row][col…col] }

Hash

attempt 5

Must be in a file called “Hello, world!”

begin
raise :foo
rescue StandardError => se
puts se.backtrace.first.match(/([^/\:]+):/)[1]
end

attempt 6

Must be in a file called “Hello, world!”

puts FILE

On Sun, Mar 2, 2008 at 11:21 PM, Bill K. [email protected] wrote:

Greetings,

My quiz solution(s) are here:

http://tastyspleen.net/~billk/ruby/quiz/158-hello-world/158_hello_world.rb

Awesome!

I decided to take a “meta” approach and created a quick and dirty code
generator. I taught it some basic Ruby Identities and hen let it have
at it. With just the 5 silly identities that it currently has it can
generate never ending variations, though they get repetitive very
quickly --nevertheless there are already some unexpected solutions. I
suppose with maybe a few dozen identities it could get pretty
interesting.

Try running like so:

ruby helloword.rb 100
ruby helloword.rb test 100
ruby helloword.rb output 100

The number is the number of solutions to generate, ‘test’ will run it
through test/unit to make sure it all checks out and ‘output’ will
print a whole bunch of "Hello, World!"s :slight_smile:

Oh, and yes, I know it’s not all that robust. It was just a fun quick
hack. But feel free to improve it and let me know if you have any good
identities to add.

T.


class SimpleCodeGenerator

def self.identities
@identities ||= []
end

def self.identity(&block)
identities << block
end

attr_reader :original
attr_accessor :alternates

def initialize(original)
@original = original
@alternates = [original]
end

def generate(limit=100)
work = original.dup
while(alternates.size < limit) do
alts = alternates.dup
size = alternates.size
alts.each do |alt|
self.class.identities.each do |identity|
self.alternates |= [identity[alt]]
break if alternates.size >= limit
end
end
end
end

def show_code
alternates.each do |code|
puts code
end
end

def show_output
alternates.each do |code|
puts run(code)
end
end

def generate_tests
original_run = run(original)
runner = method(:run)
testcase = Class.new(Test::Unit::TestCase)
alternates.each_with_index do |code, index|
testcase.class_eval do
define_method(“test_#{index}”) do
assert_equal(original_run, runner[code])
end
end
end
end

def run(code)
so = $stdout
sio = StringIO.new
$stdout, $stderr = sio, sio
eval code, $TOPLEVEL_BINDING
result = $stdout.string
$stdout = so
result
end

code identities

identity do |code|
code.sub(/puts "["]/, ‘print “\1\n”’)
end

identity do |code|
code.sub(/puts "["]/, ‘printf “%s\n” % ["\1"]’)
end

identity do |code|
code.gsub(/"["]/, ‘"\1".reverse.reverse’)
end

identity do |code|
code.gsub(/[’]/){ $1.inspect }
end

identity do |code|
code.gsub(/[’]/){ “#{$1.split(//).inspect}.join(’’)” }
end

end

if FILE == $0
cnt = (ARGV.find{ |a| /\d+/ =~ a } || 20).to_i

scg = SimpleCodeGenerator.new(“puts ‘Hello, World!’”)
scg.generate(cnt)

case ARGV[0]
when ‘test’
require ‘test/unit’
scg.generate_tests
when ‘output’
scg.show_output
else
scg.show_code
end
end

Here’s all I came up with:

class Hello; def self.world!; [self, callee].join(’ '); end; end

puts Hello.world!

Only works with Ruby 1.9 though…

Jesse M. wrote:

attempt 3

class Hello
def method_missing m; print m; self; end
end

Hello.new.H.e.l.l.o.send(’, ').w.o.r.l.d!.send("\n")

A variation:

def method_missing(*a) print *a end;h.e.l.l.o(", “).w.o.r.l.d(”!\n")

To me, the essence of a “hello, world” program is to get the phase on
the computer screen. But “on the screen” doesn’t have to mean “write
to stdout”. My three solutions all avoid stdout.

The first solution highjacks Apple’s TextEdit application.

require "appscript" include Appscript te = app('TextEdit') te.launch te.documents.end.make(:new => :document, :with_properties => {:text => "hello, world\n"})

The second solution uses an AppleScript dialog.

require "osax" include OSAX osax.display_dialog("hello, world")

These first two solutions are Apple-centric. I don’t apologize for
that. I also employed the classic Kernighan and Ritchie version, just
“hello, world”, no caps or exclamation point.

The third solution uses Tk and should run on any system with a
functioning Ruby/Tk library, but you may have to specify another
font. This one is not so minimalist as the first two. Here I use what
today seems to be the most common version of the phrase (“Hello,
World!”) just because it looks prettier in 72-point Brush Script.

require 'tk'

root = Tk.root
root.title(‘Ruby/Tk Hello’)
win_w, win_h = 360, 160
win_x = (root.winfo_screenwidth - win_w) / 2
root.geometry("#{win_w}x#{win_h}+#{win_x}+50")
root.resizable(false, false)

TkLabel.new(root) {
text ‘Hello, World!’
relief ‘solid’
borderwidth 1
font(‘family’=>‘Brush Script MT’, ‘size’=>72)
place(“x”=>10, “y”=>10, “height”=>92, “width”=>340)
}

TkButton.new(root) {
text ‘Goodbye’
command { Tk.root.destroy }
place(“x”=>138, “y”=>122, “height”=>28, “width”=>83)
}

Tk.mainloop

The use of ‘place’, rather than ‘pack’ may seem strange. I confess I
wrote the Ruby/Tk version quite some time ago when I was
experimenting with the ‘place’ layout manager.

Regards, Morton

Nothing too much for now. Wasn’t sure how unobfuscated to do them,
so i just did simple ones. Except for my first one, which flashes
different colors.

Hit to stop the loop!

http://pastie.caboo.se/160366

~ Ari
English is like a pseudo-random number generator - there are a
bajillion rules to it, but nobody cares.

def method_missing(method) puts method end
def Object.const_missing(const) print const.to_s + ", " end
[Hello, World!]

Here’s my solution:

hello, world = “”, 2645608968345021733469237830984
(hello << (world % 256); world /= 256) until world == 0
puts hello

Have a good one,

Justin

On Fri, Feb 29, 2008 at 7:06 PM, Matthew D Moss [email protected]

i – raising an HelloWorldError

class HelloWorldError < StandardError
def to_s
“Hello, World!”
end
end
module Kernel
def raise(e)
puts e
end
end
raise HelloWorldError.new

ii – a lost and found HelloWorld

class HelloWorld
def to_s
“Hello, World!”
end
end
HelloWorld.new
ObjectSpace.each_object { |o| puts o if o.is_a?(HelloWorld) }

iii – a little curry

hello = lambda { |a| “Hello, #{a.call}”}
world = lambda { “World!” }
puts hello.call(world)

iv – in only one line but to ruby instances

puts ruby -e 'puts "Hello, World!"'

v – and finally a probabilistic approach

beware this one is not tested yet!

which means the the test is still running and at

least it didn’t raise any errors so far :wink:

goal = “Hello, World!\n”
bytes = goal.split(//).map { |e| e[0] }.uniq

seed = 0
until false
srand(seed)
i = 0
while i < goal.size
c = rand(bytes.size)
break if bytes[c] != goal[i]
i += 1
end
break if i == goal.size
seed += 1
end

goal.size.times { print bytes[rand(bytes.size)].chr }

g phil

Only a set of very basic solutions:

#!/usr/bin/env ruby19

puts ‘-- Exact solutions --’

STDOUT << ‘Hello’ << ', ’ << ‘world’ << ‘!’ << “\n”

puts ‘Holle, werld!’.tr(‘eo’, ‘oe’)

puts ‘!dlrow ,olleH’.reverse

def method_missing(*a); puts ‘Hello, world!’; end; say_hi

a = [1,2,3]; def a.to_s; ‘Hello, world!’; end; puts “#{a}”

require ‘zlib’
hw = Zlib::Deflate.new.deflate(“Hello, world!”, Zlib::FINISH)
puts Zlib::Inflate.new.inflate(hw)

puts [1819043144, 1998597231, 1684828783,
538976289].pack(‘VVVV’).strip

puts (’%x’ % 10484973469620254453249450853906).scan(/…/).pack(‘h2’ *
13)

puts ‘-- Approximative solutions --’

puts ‘Hello, world!’.split(’’).map {|c| /\l/ =~ c ? ‘%c’ % (c.ord +
rand(3) - 1) : c}.join

puts ‘Hello, world!’.gsub(/\b\w{4,}?\b/) {|t| t[1…-2] =
t[1…-2].split(’’).shuffle.join; t }

puts [6.51886850036479e+265, 6.01347722536415e-154].pack(‘EE’).strip

Just wanted to say “Hello” :wink:

Probably my only solution that makes sense :wink:

puts “hello, world!”.split.map{ |x| x.capitalize }.join(’ ')

Amazingly you can do << with ints to strings

puts [?H, ?e, ?l, ?l, ?o, ?, ?\s, ?W, ?o, ?r, ?l, ?d, ?!].
inject(“”){|s,char| s << char}

A tribute to perl :wink:

def method_missing *args, &blk
puts “Hello, World”
end

croak

You cannot add strings and ints

begin
puts [?h, ?e, ?l, ?l, ?o, ?, ?\s, ?w, ?o, ?r, ?l, ?d, ?!].
inject(“”){|s,char| s + char}
abort “If you do not succeed…”
rescue
puts “!dlroW ,olleH”.reverse
end

What Mixins can do for you

module Hello
def hello_world
“Hello,”
end
end

module World
def hello_world
super <<
" World!"
end
end

class HelloWorld
extend Hello
extend World
def self.hello_world
puts super
end
end

HelloWorld.hello_world

Abusing Kernel

module Kernel
alias_method :_puts, :puts
def puts *args, &blk
_puts “Hello, World!”
end
end

puts

Metaprogramming on classes

class A
def self.inherited dummy
print “Hello,”
end
end

class B < A
class << self
def inherited dummy
print " World!"
end
end
end

class << C = Class::new( B )
def inherited dummy
puts
end
end

Class::new C

A Hommage to James’ Gödel Quiz and showing that Integers are immutable

class Integer
def inject_chars istring, &blk
return istring if zero?
( self / 256 ).inject_chars( blk.call( istring, self % 256 ), &blk )
end
end
puts 2645608968345021733469237830984.inject_chars(“”){ |s,n| s+n.chr }

A more sensible approach of abusing Kernel::puts :wink:

module Sensible
def puts *args
return Kernel::puts( *args ) unless args.empty?
Kernel::puts “Hello, World!”
end
end

include Sensible
puts
puts “Hello, Ruby Q.!”

A functional approach, introducing the splash

def print_strings *strings
return puts if strings.empty?
print strings.shift
print_strings *strings
end

print_strings %{Hello, World!}

Blocks and Procs, split(//)

module Printable
def to_proc
lambda {
each do |elem| print elem end
}
end
end
Array.send :include, Printable

def yielder
yield
end

yielder &(“Hello, World!” << 10).split(//)

A radical and viral solution

ObjectSpace.each_object(Module) do |mod|
mod.send :define_method, :hello_world do puts “Hello, World!” end
end

42.hello_world
Object.hello_world
nil.hello_world

(A = Class::new).hello_world


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein