[#319108] Iterator objects and lazy evaluation — Yuh-Ruey Chen <maian330@...>

Two questions:

14 messages 2008/11/01

[#319117] Poor performance of Ruby 1.8.7 when installed with MacPorts — abc <arcadiorubiogarcia@...>

Hi,

15 messages 2008/11/01

[#319176] Ruby for Philosophers — Sebastian Torena <citizenkant@...>

Hi there,

14 messages 2008/11/02

[#319196] ruby1.9: lazy versions of Enumerator#select and friends? — Brian Candler <b.candler@...>

I've been having a play with Enumerators in ruby 1.9, in particular

12 messages 2008/11/02

[#319239] Rake task for building latex? — Stefano Crocco <stefano.crocco@...>

Does anyone know whether there's a rake task to build latex files, including

10 messages 2008/11/03

[#319319] Ruby's take on S.O.L.I.D. — Mike Lopke <reglopke@...>

I'm curious about everyone's take on Bob Martin's S.O.L.I.D. design

16 messages 2008/11/03

[#319401] Combination of numbers in an array that add up to x — Hae Lee <hae.lee.subscription@...>

Objective: Find list of values in an array that adds up to a specific

17 messages 2008/11/04

[#319404] Showing a spinner ? — Aldric Giacomoni <aldric@...>

How do I show a spinner on the command line interface when a ruby script

13 messages 2008/11/04

[#319440] What would you like to know about JRuby? — Charles Oliver Nutter <charles.nutter@...>

Tom Enebo and I are putting together our JRuby presentation for

22 messages 2008/11/04

[#319532] What's the Best Way to Mimic an HTTP Request? — Daniel Miessler <daniel@...>

I'm trying to write a tool that will take a domain as an argument and

10 messages 2008/11/05

[#319546] Ruby has a Face that it wears on its feet — "Jayson Williams" <williams.jayson@...>

In my opinion, Ruby's official face should be Shoes. Shoes gives Ruby

17 messages 2008/11/05
[#319553] Re: Ruby has a Face that it wears on its feet — "Martin DeMello" <martindemello@...> 2008/11/05

On Wed, Nov 5, 2008 at 11:17 AM, Jayson Williams

[#319576] how to quickly find a string towards the end of a large io object — bwv549 <jtprince@...>

How do I scan starting at the end of a big io object to find a string

12 messages 2008/11/06

[#319702] Sudoku Generator (#182) — Matthew Moss <matt@...>

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

14 messages 2008/11/07

[#319769] implementing mvc - using observer pattern - beginner to OOP — Adam Akhtar <adamtemporary@...>

Hi I started making a simple command line todo list application as a way

10 messages 2008/11/08

[#319770] what's easiest way to compare a Float & BigDecimal (i.e. like a equals mechanism) — "Greg Hauptmann" <greg.hauptmann.ruby@...>

Hi,

8 messages 2008/11/08

[#319835] Moving large amount of files, 1.750.000+ — Sebastian Newstream <abeansits@...>

Hello fellow Rubyists!

15 messages 2008/11/09
[#319837] Re: Moving large amount of files, 1.750.000+ — Robert Klemme <shortcutter@...> 2008/11/09

On 09.11.2008 18:04, Sebastian Newstream wrote:

[#319861] Notepad++ (no debug output, using XP) — Ed Hardy <asm.sol@...>

Notepad++ seems to be a great editor for Ruby, in XP Windows. However,

13 messages 2008/11/10

[#319902] Problem with object methods? — Carter Davis <theshakrah@...>

I recently made an object for a game I'm making. It uses the constructor

16 messages 2008/11/10
[#319908] Re: Problem with object methods? — Hugh Sasse <hgs@...> 2008/11/10

[#319911] Re: Problem with object methods? — Carter Davis <theshakrah@...> 2008/11/10

Okay, I made an example.

[#320057] Convert text string i.e 'Peter' into integer ID — Justus Ohlhaver <ohlhaver@...>

Hello,

23 messages 2008/11/12

[#320101] Issue with block and getting to local variables — Tarek Other <cashew250@...>

Ok I'm new to ruby and want to do the following, I want to define a

12 messages 2008/11/12

[#320103] Need tutoring on using a path environment variable — dkmd_nielsen <donn@...>

I don't know what to do. I have an environment variable, PW_PATH,

11 messages 2008/11/12

[#320135] '#' characters are breaking my regexp — Max Williams <toastkid.williams@...>

I'm trying to build a regexp that includes music notes, eg Bb or C#.

14 messages 2008/11/13

[#320202] Highline - question with multiple choices — szimek <szimek@...>

Hi,

14 messages 2008/11/14
[#320208] Re: Highline - question with multiple choices — James Gray <james@...> 2008/11/14

On Nov 14, 2008, at 4:23 AM, szimek wrote:

[#320270] Re: Highline - question with multiple choices — szimek <szimek@...> 2008/11/15

On 14 Lis, 14:52, James Gray <ja...@grayproductions.net> wrote:

[#320213] Unit Conversion (#183) — Matthew Moss <matt@...>

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

37 messages 2008/11/14

[#320280] IO#lineno= doesn't work the way I expected — Chad Perrin <perrin@...>

I'm working on something that operates on each line of a file

22 messages 2008/11/15
[#320283] Re: IO#lineno= doesn't work the way I expected — Tim Hunter <TimHunter@...> 2008/11/15

Chad Perrin wrote:

[#320286] Re: IO#lineno= doesn't work the way I expected — Chad Perrin <perrin@...> 2008/11/15

On Sun, Nov 16, 2008 at 02:27:45AM +0900, Tim Hunter wrote:

[#320287] Re: IO#lineno= doesn't work the way I expected — "Michael Guterl" <mguterl@...> 2008/11/15

On Sat, Nov 15, 2008 at 2:08 PM, Chad Perrin <perrin@apotheon.com> wrote:

[#320288] Re: IO#lineno= doesn't work the way I expected — "Michael Guterl" <mguterl@...> 2008/11/15

On Sat, Nov 15, 2008 at 2:54 PM, Michael Guterl <mguterl@gmail.com> wrote:

[#320359] Why does tmail stop my CGI script form working? — Chad Perrin <perrin@...>

I decided to try TMail for the back end of a new contact page on a

14 messages 2008/11/17

[#320370] How can I overload a method in Ruby — Zhao Yi <youhaodeyi@...>

This is my class definition:

19 messages 2008/11/17
[#320374] Re: How can I overload a method in Ruby — Einar Magn俍 Boson <einarmagnus@...> 2008/11/17

there is no overloading, only overriding.

[#320417] How to extract links of a particular class type — "Sita Rami Reddy" <sitaramireddy@...>

I have a web page which has n number of links.

11 messages 2008/11/17

[#320446] function to select only certain key/value pairs from hash? — Aryk Grosz <tennisbum2002@...>

Whenever Im coding I usually come across having to create a new hash

14 messages 2008/11/17

[#320482] I don't like specs, should I change my point of view ? — Zouplaz <user@...>

Hello, I'm not trolling. I don't like specs (RSpec) : everytime I had a

18 messages 2008/11/18

[#320500] Should is the new Must? — Trans <transfire@...>

Why did 'should' become the going nomenclature of BDD framworks?

21 messages 2008/11/18

[#320553] Syntax question from a newbie to Ruby — David Spitzer <davidspitzer@...>

I am just learning Ruby and I can not seem to see why the first example

12 messages 2008/11/18

[#320655] build hash by iterating — Jason Lillywhite <jason.lillywhite@...>

I am building a hash this way:

15 messages 2008/11/19

[#320665] Question about host, gethostbyname and getaddress — Vladimir Fekete <fekete@...>

Hi *,

11 messages 2008/11/19

[#320709] ANN: One-Click Ruby Installer 186-27 Release Candidate 2 — Luis Lavena <luislavena@...>

Hello Ruby for Windows users!

11 messages 2008/11/19

[#320811] Found a ruby bug in the URI class, what do I do? — Ben Johnson <bjohnson@...>

I'm pretty sure this is a bug, and it seem so obvious that I'm thinking

9 messages 2008/11/20

[#320908] Befunge (#184) — Matthew Moss <matt@...>

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

28 messages 2008/11/22
[#321031] Re: [QUIZ] Befunge (#184) — Matthew Moss <matt@...> 2008/11/24

Hopefully the quiz isn't intimidating... It's a fairly simple language

[#321006] Can you run a command line script with arguments, without typing 'ruby' first? — "Jayson Williams" <williams.jayson@...>

Hi All,

29 messages 2008/11/24
[#321008] Re: Can you run a command line script with arguments, without typing 'ruby' first? — "Diogo Lisboa" <diogoslisboa@...> 2008/11/24

chmod a+x my_script (restrict permissions if you want)

[#321022] Re: Can you run a command line script with arguments, without typing 'ruby' first? — "Jayson Williams" <williams.jayson@...> 2008/11/24

I am using win os, so the shabang thing isn't an option for me. I put

[#321023] Re: Can you run a command line script with arguments, without typing 'ruby' first? — "Glen Holcomb" <damnbigman@...> 2008/11/24

On Mon, Nov 24, 2008 at 2:12 PM, Jayson Williams

[#321024] Re: Can you run a command line script with arguments, without typing 'ruby' first? — "Glen Holcomb" <damnbigman@...> 2008/11/24

On Mon, Nov 24, 2008 at 2:21 PM, Glen Holcomb <damnbigman@gmail.com> wrote:

[#321027] Re: Can you run a command line script with arguments, without typing 'ruby' first? — "Jayson Williams" <williams.jayson@...> 2008/11/24

The associations are correct. I reset them just to be sure though. I

[#321095] Re: Can you run a command line script with arguments, without typing 'ruby' first? — Daniel Schömer <daniel.schoemer@...> 2008/11/25

Jayson Williams wrote:

[#321037] Chris Pine tutorial assistance chapter 7 sort data without use of .sort method — jgheal@...

I'm learning to progam and came accross Chris Pine's Ruby Tutorial.

12 messages 2008/11/24

[#321039] Good math/stats libraries for Ruby? — Kenneth McDonald <kenneth.m.mcdonald@...>

There seem to be lots of small stats/math libraries for Ruby, but none

10 messages 2008/11/24

[#321166] time to back peddle? (Ruby 1.8.7) — Trans <transfire@...>

I just updated my Ubuntu system and was a bit surprised to find:

16 messages 2008/11/26

[#321179] How to get a reference to a block (when no explicit block parameter is used?) — Kenneth McDonald <kenneth.m.mcdonald@...>

In a function, I can find out if a block was given using block_given?,

8 messages 2008/11/26

[#321246] Performance issues with large files -- ruby vs. python :) — sa 125 <s_ayalon@...>

Hi all -

16 messages 2008/11/27
[#321248] Re: Performance issues with large files -- ruby vs. python :) — Florian Gilcher <flo@...> 2008/11/27

>

[#321271] Ruby's duck typing — "stephan.zimmer" <stephan.zimmer@...>

I would like to represent certain data by a list; to this end I let

17 messages 2008/11/27

[#321287] Programming Noob Chris Pine Tutorial sorting without use of array.sort method — whisperjim <jgheal@...>

I'm working through the following tutorial http://pine.fm/LearnToProgram/

10 messages 2008/11/27

[#321297] eRuby/erb outside of Rails — Jonny Noog <jonnynoog@...>

Hello,

18 messages 2008/11/28

[#321387] best gui toolkit — Warren Dulnuan <rr3800@...>

What is the best GUI toolkit for Ruby?

32 messages 2008/11/29
[#321397] Re: best gui toolkit — Vladimir Fekete <fekete@...> 2008/11/29

[#321421] Anyone scraping dynamic AJAX sites? — Becca Girl <cschall@...>

Hello.

12 messages 2008/11/30

[#321428] Enumerable#select used to return actual values — Mike Austin <"mike[nospam]"@...>

I'm pretty sure select used to use the actual value of the called block,

36 messages 2008/11/30
[#321432] Re: Enumerable#select used to return actual values — Robert Klemme <shortcutter@...> 2008/11/30

On 30.11.2008 04:46, Mike Austin wrote:

[#321906] Re: Enumerable#select used to return actual values — Mark Thomas <mark@...> 2008/12/04

On Nov 29, 10:46=A0pm, Mike Austin <"mike[nospam]"@mike-austin.com>

[#321912] Re: Enumerable#select used to return actual values — Trans <transfire@...> 2008/12/04

Re: Befunge (#184)

From: Jeff Dallien <jeff@...>
Date: 2008-11-29 22:29:28 UTC
List: ruby-talk #321418
Here is my solution. It's not a revolutionary implementation, but I
had an emphasis on readability and testing. I believe it correctly
runs all the example programs from the Befunge-93 site that the C
reference implementation does.

While debugging I had a "C interpreter mode" which did a few things
slightly differently such as division and mod with negative numbers to
match the behaviour of the reference implementation. I eventually
removed it for clarity since it didn't gain much, other than
accounting for those differences.

For example, the following program will output -1 when run with the C
implementation and -2 with a standard Ruby implementation. Solutions
to Ruby Quiz #85 have some methods which provide C-like division and
mod.

3-2/.@

I couldn't find a simple solution for single character input, so it
goes without. Thus for programs like namegame.bf you have to hit enter
between each character.

Spec file is below the source. Thanks for the interesting quiz.

Jeff Dallien
http://jeff.dallien.net/

------- befunge.rb

#!/usr/bin/env ruby
# Befunge-93 interpreter for Ruby Quiz #184
# Jeff Dallien (jeff@dallien.net)
#
class Stack
  attr_reader :stack

  def initialize
    @stack = []
  end

  def pop
    return 0 if @stack.empty?
    @stack.pop
  end

  def push(value)
    @stack.push(value)
  end

  def swap!
    first  = pop
    second = pop
    push(first)
    push(second)
  end

  def dup!
    top = pop
    push(top)
    push(top)
  end
end

class Instruction
  attr_reader :value

  def initialize(value)
    @value = value
  end

  # digits 0-9
  def value_for_stack?
    (@value[0] >= 48 && @value[0] <= 57)
  end

  # " (double quote) toggles string mode
  def string_mode_toggle?
    (34 == @value[0])
  end
end

class ProgramCounter
  attr_reader :x
  attr_reader :y
  attr_accessor :direction

  def initialize
    @x = 0
    @y = 0
    @direction = :right
  end

  def move!
    send("move_#{@direction}!")
  end

  private

  def move_right!
    @x = (@x + 1) % 80
  end

  def move_left!
    @x = (@x - 1) % 80
  end

  def move_down!
    @y = (@y + 1) % 25
  end

  def move_up!
    @y = (@y - 1) % 25
  end
end

class BefungeProgram
  def initialize
    @program = []
  end

  def load_from_file(filename)
    File.open(filename) do |f|
      25.times do
        add_program_line(f.gets.to_s)
      end
    end
  end

  def [](index)
    @program[index]
  end

  def load_from_string_array(program_strings)
    25.times do |index|
      add_program_line(program_strings[index].to_s)
    end
  end

  private

  def add_program_line(line)
    padded_line = line.chomp[0..80].ljust(80)
    @program << padded_line.split('').map { |c| c[0] }
  end
end


class Befunger
  INSTRUCTION_TABLE = { '@'  => :exit,
                        ' '  => :blank,
                        '\\' => :swap,
                        ':'  => :dup,
                        '$'  => :pop,
                        ','  => :output_ascii,
                        '.'  => :output_int,
                        '+'  => :add,
                        '-'  => :subtract,
                        '*'  => :multiply,
                        '/'  => :divide,
                        '%'  => :mod,
                        '!'  => :not,
                        '`'  => :greater,
                        '>'  => :pc_right,
                        '<'  => :pc_left,
                        '^'  => :pc_up,
                        'v'  => :pc_down,
                        '?'  => :pc_random,
                        '_'  => :horizontal_if,
                        '|'  => :vertical_if,
                        'g'  => :get,
                        'p'  => :put,
                        '&'  => :input_value,
                        '~'  => :input_character,
                        '#'  => :bridge,
                        '"'  => :toggle_string_mode
                      }


  def initialize(program)
    @program     = program
    @pc          = ProgramCounter.new
    @stack       = Stack.new
    @exit_called = false
    @string_mode = false
  end

  def run
    until @exit_called
      execute_instruction
      @pc.move!
    end
  end

  private

  # used so that output can be captured during testing
  def output(value)
    print value
    STDOUT.flush
  end

  def read_instruction
    Instruction.new(@program[@pc.y][@pc.x].chr)
  end

  def execute_instruction
    instruction = read_instruction

    if @string_mode && !instruction.string_mode_toggle?
      @stack.push(instruction.value[0])
    elsif instruction.value_for_stack?
      @stack.push(instruction.value.to_i)
    else
      begin
        send(INSTRUCTION_TABLE[instruction.value])
      rescue TypeError, NoMethodError
        raise "Unknown instruction: #{instruction.inspect}"
      end
    end
  end

  def exit
    @exit_called = true
  end

  def blank
  end

  def swap
    @stack.swap!
  end

  def dup
    @stack.dup!
  end

  def pop
    @stack.pop
  end

  def output_ascii
    value = @stack.pop
    output value.chr
  end

  def output_int
    value = @stack.pop
    output "#{value.to_i} "
  end

  def generic_math_instruction(operation)
    rhs = @stack.pop
    lhs = @stack.pop
    result = lhs.send(operation, rhs)
    @stack.push(result)
  end

  def add
    generic_math_instruction('+')
  end

  def subtract
    generic_math_instruction('-')
  end

  def divide
    generic_math_instruction('/')
  end

  def mod
    generic_math_instruction('%')
  end

  def multiply
    generic_math_instruction('*')
  end

  def not
    value = @stack.pop
    result = (value == 0) ? 1 : 0
    @stack.push(result)
  end

  def greater
    rhs = @stack.pop
    lhs = @stack.pop
    result = (lhs > rhs) ? 1 : 0
    @stack.push(result)
  end

  def pc_right
    @pc.direction = :right
  end

  def pc_left
    @pc.direction = :left
  end

  def pc_up
    @pc.direction = :up
  end

  def pc_down
    @pc.direction = :down
  end

  def pc_random
    directions = [:right, :left, :up, :down]
    @pc.direction = directions[rand(4)]
  end

  def horizontal_if
    value = @stack.pop
    @pc.direction = (value == 0) ? :right : :left
  end

  def vertical_if
    value = @stack.pop
    @pc.direction = (value == 0) ? :down : :up
  end

  def get
    y = @stack.pop
    x = @stack.pop
    @stack.push(@program[y][x])
  end

  def put
    y = @stack.pop
    x = @stack.pop
    @program[y][x] = @stack.pop
  end

  def input_value
    input = $stdin.gets.to_i
    @stack.push(input)
  end

  def input_character
    input_char = $stdin.gets[0]
    @stack.push(input_char)
  end

  def bridge
    @pc.move!
  end

  def toggle_string_mode
    @string_mode = !@string_mode
  end
end

if $0 == __FILE__
  if ARGV[0]
    program  = BefungeProgram.new
    program.load_from_file(ARGV[0])
    befunger = Befunger.new(program)
    befunger.run
  else
    puts "Usage: ruby befunge.rb program.bf"
  end
end

-------- befunge_spec.rb

require 'befunge'

describe Stack, "popping a value" do
  before :each do
    @it = Stack.new
  end

  it "should return a zero when attempting to pop from an empty stack"
do
    @it.pop.should == 0
  end
end

describe Befunger, "processing instructions" do
  before :each do
    @output  = ''
    @stack   = Stack.new
    @pc      = ProgramCounter.new
    @program = BefungeProgram.new
    ProgramCounter.should_receive(:new).and_return(@pc)
    Stack.should_receive(:new).and_return(@stack)
  end

  def run_program(program_strings)
    @program.load_from_string_array(program_strings)
    processor = Befunger.new(@program)
    processor.should_receive(:output).any_number_of_times { |o|
@output << o }
    processor.run
  end

  describe "blank instruction" do
    before :each do
      run_program(["   @",
                   "111@",
                   "@@@@"])
    end

    it "should not add any value the stack" do
      @stack.pop.should == 0
    end

    it "should not change the program counter direction" do
      @pc.direction.should == :right
    end
  end

  describe "an unknown instruction" do
    it "should raise an error" do
      lambda { run_program(["=@"]) }.should raise_error(/Unknown
instruction/)
    end
  end

  describe "add instruction" do
    before :each do
      run_program(["12+@"])
    end

    it "should put the result of the addition on the stack" do
     @stack.pop.should == 3
    end
  end

  describe "substract instruction" do
    describe "with a positive result" do
      before :each do
        run_program(["65-@"])
      end

      it "should put the correct result on the stack" do
        @stack.pop.should == 1
      end
    end

    describe "with a negative result" do
      before :each do
        run_program(["56-@"])
      end

      it "should put the correct result on the stack" do
        @stack.pop.should == -1
      end
    end
  end

  describe "multiplication instruction" do
    before :each do
      run_program(["55*@"])
    end

    it "should put the correct result on the stack" do
      @stack.pop.should == 25
    end
  end

  describe "mod instruction" do
    describe "calculating with positive numbers" do
      before :each do
        run_program(["52%@"])
      end

      it "should put the correct value on the stack" do
        @stack.pop.should == 1
      end
    end

    describe "calculating with a negative number" do
      before :each do
        run_program(["1-2*3%@"])
      end

      it "should put the correct value on the stack" do
        @stack.pop.should == 1
      end
    end
  end

  describe "division instruction" do
    describe "calculating with positive numbers" do
      before :each do
        run_program(["93/@"])
      end

      it "should put the correct value on the stack" do
        @stack.pop.should == 3
      end
    end

    describe "calculating with negative numbers" do
      before :each do
        run_program(["3-2/@"])
      end

      it "should put the correct negative value on the stack" do
        @stack.pop.should == -2
      end
    end
  end

  describe "swap instruction" do
    before :each do
      run_program(["123\\@"])
    end

    it "should swap the two top values of the stack" do
      @stack.pop.should == 2
      @stack.pop.should == 3
    end

    it "should not change the anything below the top two values" do
      @stack.pop
      @stack.pop
      @stack.pop.should == 1
    end
  end

  describe "duplication instruction" do
    before :each do
      run_program(["1:@"])
    end

    it "should put two copies of the value on the stack" do
      @stack.pop.should == 1
      @stack.pop.should == 1
    end
  end

  describe "pop instruction" do
    before :each do
      run_program(["123$@"])
    end

    it "should remove a value from the stack" do
      @stack.pop.should == 2
      @stack.pop.should == 1
    end

    it "should not output anything" do
      @output.should == ''
    end
  end

  describe "not instruction" do
    describe "with a 0 on the top of the stack" do
      before :each do
        run_program(["0!@"])
      end

      it "should put a 1 on top of the stack" do
        @stack.pop.should == 1
      end
   end

   describe "with a non-zero value on the top of the stack" do
     before :each do
       run_program(["1!@"])
     end

     it "should put a 0 on top of the stack" do
       @stack.pop.should == 0
     end
   end
  end

  describe "greater instruction" do
    describe "with the larger value placed on the stack first" do
      before :each do
        run_program(["52`@"])
      end

      it "should place a 1 on the top of the stack" do
        @stack.pop.should == 1
      end

      it "should remove the compared values from the stack" do
        @stack.pop
        @stack.pop.should == 0
      end
    end

    describe "with the smaller value placed on the stack first" do
      before :each do
        run_program(["38`@"])
      end

      it "should put a 0 on the top of the stack" do
        @stack.pop.should == 0
      end
    end

    describe "comparing the same value" do
      before :each do
        run_program(["44`@"])
      end

      it "should place a 0 on the top of the stack" do
        @stack.pop.should == 0
      end
    end
  end


  describe "bridge instruction" do
    before :each do
      run_program(["123#...@"])
    end

    it "should skip the next instruction" do
      @output.should == "3 2 "
    end

    it "should leave remaining values on the stack" do
      @stack.pop.should == 1
    end
  end

  describe "ASCII output instruction" do
    before :each do
      run_program(["665+*1-,@"])
    end

    it "should output the ASCII character of the value on the top of
the stack" do
      @output.should == "A"
    end
  end

  describe "integer output instruction" do
    before :each do
      run_program(["665+*1-.@"])
    end

    it "should output the integer on the top of the stack, followed by
a space" do
      @output.should == "65 "
    end
  end

  describe "string mode" do
    before :each do
      run_program(["\"Ab\"@"])
    end

    it "should place the ASCII values on the stack" do
      @stack.pop.should == 98
      @stack.pop.should == 65
    end
  end

  describe "get instruction" do
    describe "getting a value from within the given program" do
      before :each do
        run_program(["11g@",
                     " *   "])
      end

      it "should get the value from the program and put it on the
stack" do
        @stack.pop.should == '*'[0]
      end
    end

    describe "getting a value outside the given program but in the
program space" do
      before :each do
        run_program(["88g@"])
      end

      it "should put the ASCII value of the space character (32) on
the stack" do
        @stack.pop.should == 32
      end
    end

    describe "attempting to get a value outside the 80x25 program
space" do
      it "should raise an error" do
       lambda { run_program(["066*g@"]) }.should raise_error
      end
    end
  end

  describe "put instruction" do
    describe "within the 80x25 program space" do
      before :each do
        run_program(["522p@"])
      end

      it "should put the correct value inside the program space" do
        @program[2][2].should == 5
      end
    end

    describe "outside the 80x25 program space" do
      it "should raise an error" do
        lambda { run_program(["1188*p@"]) }.should raise_error
      end
    end
  end

  describe "horizontal if instruction" do
    def horizontal_if_program(stack_value)
      run_program(["#{stack_value}          v             @ ",
                                '@,,,,"left"_"thgir",,,,, @ ',
                                '           @               '])
    end

    describe "with a zero on top of the stack" do
      before :each do
        horizontal_if_program('0')
      end

      it "should move the program counter to the right" do
        @output.should == "right"
      end
    end

    describe "with a non-zero value on top of the stack" do
      before :each do
        horizontal_if_program('4')
      end

      it "should move the program counter to the left" do
        @output.should == "left"
      end
    end
  end

  describe "vertical if instruction" do
    def vertical_if_program(stack_value)
      run_program(["#{stack_value}           |@",
                                '            5 ',
                                '            @ ',
                                '            4 '])
    end

    describe "with a zero on top of the stack" do
      before :each do
        vertical_if_program('0')
      end

      it "should move the program counter down" do
        @stack.pop.should == 5
      end
    end

    describe "with a non-zero value on top of the stack" do
      before :each do
        vertical_if_program('2')
      end

      it "should move the program counter up" do
        @stack.pop.should == 4
      end
    end
  end

  describe "controlling the program counter direction" do
    describe "to the up direction" do
      before :each do
        run_program(["  ^@",
                     "  @",
                     "  7"])
      end

      it "should set the program counter direction to :up" do
         @pc.direction.should == :up
      end

      it "should move upwards and loop to the bottom of the program"
do
        @stack.pop.should == 7
      end
    end

    describe "to the down direction" do
      before :each do
        run_program(["v8@",
                     " @ ",
                     ">v@"])
      end

      it "should set the program counter direction to :down" do
        @pc.direction.should == :down
      end

      it "should move downwards and loop to the top of the program" do
        @stack.pop.should == 8
      end
    end

    describe "to the left direction" do
      before :each do
        run_program(["<@5"])
      end

      it "should set the program counter direction to :left" do
        @pc.direction.should == :left
      end

      it "should move left and loop to the right side of the program"
do
        @stack.pop.should == 5
      end
    end

    describe "to the right direction" do
      describe "as the default direction" do
        before :each do
          run_program(["   1@"])
        end

        it "should set the program counter direction to :right" do
          @pc.direction.should == :right
        end

        it "should move right when a program starts" do
          @stack.pop.should == 1
        end
      end

      describe "and reaching the edge of the program" do
        before :each do
          run_program(["     v ",
                       "2@   > ",
                       "     @ "])
        end

        it "should move right and loop to the left side of the
program" do
          @stack.pop.should == 2
        end
      end
    end

    describe "in a random direction" do
      before :each do
        srand(3)  # force predictable 'random' numbers, will always
choose :up first
        run_program(["v@ ",
                     ">?@",
                     " @ "])
      end

      it "should set the program counter direction based on the random
number" do
        @pc.direction.should == :up
      end
    end
  end
end

In This Thread