parent
							
								
									94c6ccb87b
								
							
						
					
					
						commit
						298d0c3439
					
				@ -0,0 +1,99 @@
 | 
				
			||||
#!/usr/bin/env julia
 | 
				
			||||
 | 
				
			||||
using Test
 | 
				
			||||
 | 
				
			||||
mutable struct Monkey
 | 
				
			||||
  index :: UInt
 | 
				
			||||
  items :: Vector{Int}
 | 
				
			||||
  op :: Function
 | 
				
			||||
  op_value :: Int
 | 
				
			||||
  test_divisor :: Int
 | 
				
			||||
  test_result :: NTuple{2, UInt}
 | 
				
			||||
  inspected :: Int
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
function parse_monkey(text)
 | 
				
			||||
  lines = split(text, '\n')
 | 
				
			||||
  # Monkey 0:
 | 
				
			||||
  match_index = match(r"Monkey (\d+):", lines[1])
 | 
				
			||||
  index = parse(UInt, match_index.captures[1])
 | 
				
			||||
  #   Starting items: 79, 98
 | 
				
			||||
  match_items = match(r" *Starting items: (.*)", lines[2])
 | 
				
			||||
  items_list = split(match_items.captures[1], ", ")
 | 
				
			||||
  items = parse.(Int, items_list)
 | 
				
			||||
  #   Operation: new = old * 19
 | 
				
			||||
  match_op = match(r" *Operation: new = old (.) (old|\d+)", lines[3])
 | 
				
			||||
  if match_op.captures[1] == "+"
 | 
				
			||||
    op = +
 | 
				
			||||
  elseif match_op.captures[1] == "*"
 | 
				
			||||
    op = *
 | 
				
			||||
  else
 | 
				
			||||
    throw(DomainError("Unknown op: " * match_op.captures[1]))
 | 
				
			||||
  end
 | 
				
			||||
  if match_op.captures[2] == "old"
 | 
				
			||||
    op = ^
 | 
				
			||||
    op_value = 2
 | 
				
			||||
  else
 | 
				
			||||
    op_value = parse(Int, match_op.captures[2])
 | 
				
			||||
  end
 | 
				
			||||
  #   Test: divisible by 13
 | 
				
			||||
  match_test = match(r" *Test: divisible by (\d+)", lines[4])
 | 
				
			||||
  test_divisor = parse(Int, match_test.captures[1])
 | 
				
			||||
  #   If true: throw to monkey 1
 | 
				
			||||
  #   If false: throw to monkey 3
 | 
				
			||||
  match_true = match(r" *If true: throw to monkey (\d+)", lines[5])
 | 
				
			||||
  match_false = match(r" *If false: throw to monkey (\d+)", lines[6])
 | 
				
			||||
  test_result = (parse(UInt, match_true.captures[1]) + 1,
 | 
				
			||||
                 parse(UInt, match_false.captures[1]) + 1)
 | 
				
			||||
  return Monkey(index, items, op, op_value, test_divisor, test_result, 0)
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
function read_monkeys(infile)
 | 
				
			||||
  open(infile) do io
 | 
				
			||||
    monkey_strings = split(read(io, String), "\n\n")
 | 
				
			||||
    return parse_monkey.(monkey_strings)
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
function simian_shenanigans(monkeys :: Vector{Monkey})
 | 
				
			||||
  for m in monkeys
 | 
				
			||||
    for item in m.items
 | 
				
			||||
      new_value = m.op(item, m.op_value)
 | 
				
			||||
      new_value = Int(floor(new_value / 3))
 | 
				
			||||
      new_monkey = (mod(new_value, m.test_divisor) == 0
 | 
				
			||||
                    ? m.test_result[1] : m.test_result[2])
 | 
				
			||||
      push!(monkeys[new_monkey].items, new_value)
 | 
				
			||||
      m.inspected += 1
 | 
				
			||||
    end
 | 
				
			||||
    empty!(m.items)
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
function monkey_business(monkeys; rounds=20)
 | 
				
			||||
  for _ in 1:rounds
 | 
				
			||||
    simian_shenanigans(monkeys)
 | 
				
			||||
  end
 | 
				
			||||
  return prod(sort([m.inspected for m in monkeys])[end-1:end])
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
function test()
 | 
				
			||||
  @testset "monkey business" verbose=true begin
 | 
				
			||||
    @test monkey_business(read_monkeys("example.txt")) == 10605
 | 
				
			||||
    @test monkey_business(read_monkeys("input.txt")) == 64032
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
function main()
 | 
				
			||||
  if size(ARGS, 1) == 0
 | 
				
			||||
    test()
 | 
				
			||||
  else
 | 
				
			||||
    infile = ARGS[1]
 | 
				
			||||
    println("infile = ", infile)
 | 
				
			||||
    monkeys = read_monkeys(infile)
 | 
				
			||||
    display(monkeys)
 | 
				
			||||
    println()
 | 
				
			||||
    println("monkey business ", monkey_business(monkeys))
 | 
				
			||||
  end
 | 
				
			||||
end
 | 
				
			||||
 | 
				
			||||
main()
 | 
				
			||||
@ -0,0 +1,27 @@
 | 
				
			||||
Monkey 0:
 | 
				
			||||
  Starting items: 79, 98
 | 
				
			||||
  Operation: new = old * 19
 | 
				
			||||
  Test: divisible by 23
 | 
				
			||||
    If true: throw to monkey 2
 | 
				
			||||
    If false: throw to monkey 3
 | 
				
			||||
 | 
				
			||||
Monkey 1:
 | 
				
			||||
  Starting items: 54, 65, 75, 74
 | 
				
			||||
  Operation: new = old + 6
 | 
				
			||||
  Test: divisible by 19
 | 
				
			||||
    If true: throw to monkey 2
 | 
				
			||||
    If false: throw to monkey 0
 | 
				
			||||
 | 
				
			||||
Monkey 2:
 | 
				
			||||
  Starting items: 79, 60, 97
 | 
				
			||||
  Operation: new = old * old
 | 
				
			||||
  Test: divisible by 13
 | 
				
			||||
    If true: throw to monkey 1
 | 
				
			||||
    If false: throw to monkey 3
 | 
				
			||||
 | 
				
			||||
Monkey 3:
 | 
				
			||||
  Starting items: 74
 | 
				
			||||
  Operation: new = old + 3
 | 
				
			||||
  Test: divisible by 17
 | 
				
			||||
    If true: throw to monkey 0
 | 
				
			||||
    If false: throw to monkey 1
 | 
				
			||||
@ -0,0 +1,55 @@
 | 
				
			||||
Monkey 0:
 | 
				
			||||
  Starting items: 83, 88, 96, 79, 86, 88, 70
 | 
				
			||||
  Operation: new = old * 5
 | 
				
			||||
  Test: divisible by 11
 | 
				
			||||
    If true: throw to monkey 2
 | 
				
			||||
    If false: throw to monkey 3
 | 
				
			||||
 | 
				
			||||
Monkey 1:
 | 
				
			||||
  Starting items: 59, 63, 98, 85, 68, 72
 | 
				
			||||
  Operation: new = old * 11
 | 
				
			||||
  Test: divisible by 5
 | 
				
			||||
    If true: throw to monkey 4
 | 
				
			||||
    If false: throw to monkey 0
 | 
				
			||||
 | 
				
			||||
Monkey 2:
 | 
				
			||||
  Starting items: 90, 79, 97, 52, 90, 94, 71, 70
 | 
				
			||||
  Operation: new = old + 2
 | 
				
			||||
  Test: divisible by 19
 | 
				
			||||
    If true: throw to monkey 5
 | 
				
			||||
    If false: throw to monkey 6
 | 
				
			||||
 | 
				
			||||
Monkey 3:
 | 
				
			||||
  Starting items: 97, 55, 62
 | 
				
			||||
  Operation: new = old + 5
 | 
				
			||||
  Test: divisible by 13
 | 
				
			||||
    If true: throw to monkey 2
 | 
				
			||||
    If false: throw to monkey 6
 | 
				
			||||
 | 
				
			||||
Monkey 4:
 | 
				
			||||
  Starting items: 74, 54, 94, 76
 | 
				
			||||
  Operation: new = old * old
 | 
				
			||||
  Test: divisible by 7
 | 
				
			||||
    If true: throw to monkey 0
 | 
				
			||||
    If false: throw to monkey 3
 | 
				
			||||
 | 
				
			||||
Monkey 5:
 | 
				
			||||
  Starting items: 58
 | 
				
			||||
  Operation: new = old + 4
 | 
				
			||||
  Test: divisible by 17
 | 
				
			||||
    If true: throw to monkey 7
 | 
				
			||||
    If false: throw to monkey 1
 | 
				
			||||
 | 
				
			||||
Monkey 6:
 | 
				
			||||
  Starting items: 66, 63
 | 
				
			||||
  Operation: new = old + 6
 | 
				
			||||
  Test: divisible by 2
 | 
				
			||||
    If true: throw to monkey 7
 | 
				
			||||
    If false: throw to monkey 5
 | 
				
			||||
 | 
				
			||||
Monkey 7:
 | 
				
			||||
  Starting items: 56, 56, 90, 96, 68
 | 
				
			||||
  Operation: new = old + 7
 | 
				
			||||
  Test: divisible by 3
 | 
				
			||||
    If true: throw to monkey 4
 | 
				
			||||
    If false: throw to monkey 1
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue