[ create a new paste ] login | about

Link: http://codepad.org/IMrTpXA2    [ raw code | output | fork ]

aks - Ruby, pasted on May 2:
#!/usr/bin/env ruby
#
#  find_first_singleton.rb
# 
#  Given a string, find the first character that appears only once in the
#  string. For instance, given the string “aabbcddd”, the first character
#  that appears only once is the “c” found at the 4th character in the
#  string, counting from 0. Be sure that your program properly handles the
#  case that all characters appear more than once.

# % find_first_singleton -unrepeated-char 'somestring'
# o

# String.each_char_with_index {|c| code block with #c }

class String

  def each_char_with_index
    x = 0
    while x < self.length do
      char = self[x,1]
      yield [char, x]
      x += 1
    end
  end

  # String.find_first_singleton(char) => [char, index] or nil

  def find_first_singleton
    letters = {}                  # hash of letters & occurences

    self.each_char_with_index do |letter, x|
      letters[letter] ||= 0
      letters[letter] += 1
    end

    # all letters counted; find the first with count == 1
    self.each_char_with_index do |letter, x|
      return [letter, x] if letters[letter] == 1 
    end
    nil
  end
end # String enhancement

  # [letter, index].pretty => "#{letter} at #{index}"

class Array

  # [x, y].compare([r, s])
  def compare(pair)
    s, x = pair
    return true if self.nil? && s.nil?
    return false if self.nil?
    self[0] == s && self[1] == x
  end

  def pretty
    self.nil? ? 'nil' : self[0].to_s + ' at ' + self[1].to_s
  end
end

class NilClass
  def pretty
    'nil'
  end
end

def run_tests
  tests = [ ['foo',      ['f', 0]],
            ['foobar',   ['f', 0]],
            ['oofbar',   ['f', 2]],
            ['foofbar',  ['b', 4]],
            ['foofbab',  ['a', 5]],
            ['foofbob',  [ nil  ]],
            ['bar',      ['b', 0]],
            ['barboy',   ['a', 1]],
            ['barfbag',  ['r', 2]],
            ['barfbar',  ['f', 3]],
            ['barffrab', [ nil ]]
  ]
  testc = 0
  while testc < tests.size do
    instr, answer = tests[testc]
    testc += 1
    printf "Test %02d: %10s => ", testc, instr
    result = instr.find_first_singleton
    if answer.compare(result)
      puts "OK: #{result.pretty}\n"
    else
      puts "Failed: got #{result.pretty}; should be #{answer.pretty}"
    end
  end
  exit
end # run_tests

if ARGV.size < 1          # if no args, run tests
  run_tests
else
  str = ARGV.shift        # get the argument
  puts "Input: #{str}"
  puts str.find_first_singleton.pretty
end

exit


Output:
1
2
3
4
5
6
7
8
9
10
11
Test 01:        foo => OK: f at 0
Test 02:     foobar => OK: f at 0
Test 03:     oofbar => OK: f at 2
Test 04:    foofbar => OK: b at 4
Test 05:    foofbab => OK: a at 5
Test 06:    foofbob => OK: nil
Test 07:        bar => OK: b at 0
Test 08:     barboy => OK: a at 1
Test 09:    barfbag => OK: r at 2
Test 10:    barfbar => OK: f at 3
Test 11:   barffrab => OK: nil


Create a new paste based on this one


Comments: