Skip to content

Instantly share code, notes, and snippets.

@misternu
Created February 28, 2017 01:31
Show Gist options
  • Select an option

  • Save misternu/6e9fbfe4b1e16d1e32a933e3cd1e10bf to your computer and use it in GitHub Desktop.

Select an option

Save misternu/6e9fbfe4b1e16d1e32a933e3cd1e10bf to your computer and use it in GitHub Desktop.
This solves a riddle way too explicitly, yay!
def game_rules(items)
boat_west = items[0]
wolf_west = items[1]
duck_west = items[2]
grain_west = items[3]
return false if (!wolf_west && !duck_west) && boat_west
return false if (!duck_west && !grain_west) && boat_west
return false if (wolf_west && duck_west) && !boat_west
return false if (duck_west && grain_west) && !boat_west
true
end
def game_rules2(items)
!(items[0] && (!items[1] && !items[2])) &&
!(items[0] && (!items[2] && !items[3])) &&
!(!items[0] && (items[1] && items[2])) &&
!(!items[0] && (items[2] && items[3]))
end
def game_rules3(items)
!(items[0] && ((!items[1] && !items[2]) || (!items[2] && !items[3]))) &&
!(!items[0] && ((items[1] && items[2]) || (items[2] && items[3])))
end
def game_rules4(items)
!(items[0] && !items[2] && (!items[1] || !items[3])) &&
!(!items[0] && items[2] && (items[1] || items[3]))
end
# Where items is A, B, C, D
# NOT(A AND NOT(C) AND (NOT(B) OR NOT(D))) AND NOT(NOT(A) AND NOT(C) AND (A OR C))
def test(&block)
p yield([false, false, false, false]) == true
p yield([false, false, false, true]) == true
p yield([false, false, true, false]) == true
p yield([false, false, true, true]) == false # Duck alone with grain
p yield([false, true, false, false]) == true
p yield([false, true, false, true]) == true
p yield([false, true, true, false]) == false # Wolf alone with duck
p yield([false, true, true, true]) == false # All alone without boat
p yield([true, false, false, false]) == false # All alone without boat
p yield([true, false, false, true]) == false # Wolf alone with duck
p yield([true, false, true, false]) == true
p yield([true, false, true, true]) == true
p yield([true, true, false, false]) == false # Duck alone with grain
p yield([true, true, false, true]) == true
p yield([true, true, true, false]) == true
p yield([true, true, true, true]) == true
end
# test { |state| game_rules(state) }
# test { |state| game_rules2(state) }
# test { |state| game_rules3(state) }
# test { |state| game_rules4(state) }
def all_moves(items)
# find the possible moves from this current state, even illegal ones
moves = []
if items[0]
# Then we are moving the boat from west to east
moves << [false] + items[1..-1]
# If there is a wolf here, try bringing it too
moves << [false, false] + items[2..-1] if items[1]
# If there is a duck here, try bringing it too
moves << [false] + [items[1]] + [false] + [items[3]] if items[2]
# If there is grain here, try bringing it too
moves << [false] + items[1..2] + [false] if items[3]
else
# Then we are moving the boat from east to west
moves << [true] + items[1..-1]
# If there is a wolf here, try bringing it too
moves << [true, true] + items[2..-1] if !items[1]
# If there is a duck here, try bringing it too
moves << [true] + [items[1]] + [true] + [items[3]] if !items[2]
# If there is grain here, try bringing it too
moves << [true] + items[1..2] + [true] if !items[3]
end
moves
end
def all_moves2(items)
moves = []
# Try moving just the boat
moves << [!items[0]] + items[1..-1]
# If the boat is with the wolf, move the wolf
moves << [!items[0], !items[1], items[2], items[3]] if items[0] == items[1]
# If the boat is with the duck, move the duck
moves << [!items[0], items[1], !items[2], items[3]] if items[0] == items[2]
# If the boat is with the grain, move the grain
moves << [!items[0], items[1], items[2], !items[3]] if items[0] == items[3]
# Return the moves
moves
end
# starting game state = [true, true, true, true]
def solve(items = [true, true, true, true], previous_states = [])
return previous_states + [items] if items.none?
# Get all the moves
moves = all_moves2(items)
# Keep only the ones that are legal and we haven't tried on this branch
viable_moves = moves.select do |move|
game_rules4(move) && !previous_states.include?(move)
end
# Try all the viable moves (What happens here if there are no moves?)
viable_moves.each do |move|
new_previous_states = previous_states.dup.push(items)
result = solve(move, new_previous_states)
return result if result
end
# Alas, this branch is dead
return false
end
solve.each do |step|
p step
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment