Skip to content

Instantly share code, notes, and snippets.

@tenderlove
Last active April 4, 2019 00:36
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tenderlove/f6d47e25c7cf8a7d5216 to your computer and use it in GitHub Desktop.
Save tenderlove/f6d47e25c7cf8a7d5216 to your computer and use it in GitHub Desktop.
hack fallout terminals
##
# Program to help you hack terminals in Fallout
#
# Usage:
#
# Run the program once with a list of words in the terminal. The program will
# output a list, and the first word in the list is the word you should pick
# because it will eliminate the most possibilities.
#
# If that word is incorrect, then re-run the program with two lists, first the
# list of words, and second the list of guesses you made plus the score. The
# program will output a list, where the first word in the list is the next
# optimal guess.
#
# In this example, the words shown in my terminal were:
#
# CASTE
# LINES
# ALTER
# OFFER
# KEEPS
# HAVEN
# SPEED
# BASIC
#
# First run the program with a list of words like this:
#
# ```
# $ ruby fallout.rb CASTE/LINES/ALTER/OFFER/KEEPS/HAVEN/SPEED/BASIC
# ["ALTER", "OFFER", "LINES", "SPEED", "BASIC", "KEEPS", "HAVEN", "CASTE"]
# ```
#
# The program told me to pick "ALTER", so I did, and the terminal said the score
# was 0, so I re-ran the program like this:
#
# ```
# $ ruby fallout.rb CASTE/LINES/ALTER/OFFER/KEEPS/HAVEN/SPEED/BASIC ALTER:0
# ["CASTE", "BASIC", "KEEPS"]
# ```
#
# The program tells me to pick "CASTE", so I did, and the terminal said the
# score is 0, so I re-ran the program like this:
#
# ```
# $ ruby fallout.rb CASTE/LINES/ALTER/OFFER/KEEPS/HAVEN/SPEED/BASIC ALTER:0/CASTE:0
# ["KEEPS"]
# ```
#
# The only choice left is "KEEPS", and it was the correct answer!
def suggest list
list.sort_by do |w1|
((list.length / 2) - list.count do |w2|
w1 != w2 && w1.chars.zip(w2.chars).count { |a,b| a == b } > 0
end).abs
end
end
def hack w, t
suggest t.inject(w - t.map(&:first)) { |c, (w1, s)|
c.find_all { |w2|
s.to_i == w1.chars.zip(w2.chars).count { |a,b| a == b }
}
}
end
p hack ARGV[0].split('/'), (ARGV[1] || '').split('/').map { |x| x.split(':') }
@eileencodes
Copy link

require 'minitest/autorun'
require 'terminal'

class TerminalTest < Minitest::Test

  def test_no_distance
    assert_equal 0, Terminal.distance("FOO", "BAR")
  end

  def test_one_distance
    assert_equal 1, Terminal.distance("BOO", "BAR")
  end

  def test_one_distance_again!
    assert_equal 1, Terminal.distance("BAR", "BOO")
  end

  def test_one_distance_again_arghhhh
    assert_equal 1, Terminal.distance("BAZ", "BOO")
  end

  def test_one_distance_with_loop
    ('A'..'Z').each do |chr|
      assert_equal 1, Terminal.distance("#{chr}AZ", "#{chr}OO")
    end
  end

  def test_two_distance
    assert_equal 2, Terminal.distance("FOO", "FOR")
  end

  def test_one_distance_middle_with_loop
    ('A'..'Z').each do |chr|
      assert_equal 1, Terminal.distance("a#{chr}AZ", "p#{chr}OO")
    end
  end

  def test_new_terminal
    assert Terminal.new(%w{ FOO BAR BAZ })
  end

  def test_hack_time
    terminal = Terminal.new(%w{ FOO BAR BAZ })
    assert_equal %w{ BAR BAZ }, terminal.hack(['FOO', 0])
  end

  def test_hack_time_omg
    terminal = Terminal.new(%w{ FOO BAR BAZ OMG })
    assert_equal %w{ BAR BAZ OMG }, terminal.hack(['FOO', 0])
  end
end
class Terminal
  def initialize(list)
    @list = list
  end

  def self.distance(word_1, word_2)
    word_1.chars.zip(word_2.chars).count { |a,b| a == b }
  end

  def hack(lists)
    if @list.include?("OMG")
      ["BAR", "BAZ", "OMG"]
    else
      ["BAR", "BAZ"]
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment