You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							98 lines
						
					
					
						
							2.2 KiB
						
					
					
				
			
		
		
	
	
							98 lines
						
					
					
						
							2.2 KiB
						
					
					
				#!/usr/bin/env julia
 | 
						|
 | 
						|
using Test
 | 
						|
 | 
						|
function parse_stacks_line(line)
 | 
						|
  parts = Iterators.partition(line, 4)
 | 
						|
  return [s[2] for s in parts]
 | 
						|
end
 | 
						|
 | 
						|
function read_stacks(io)
 | 
						|
  stacks = Vector{Vector{Char}}()
 | 
						|
  for line in eachline(io)
 | 
						|
    if isempty(line)
 | 
						|
      return stacks
 | 
						|
    end
 | 
						|
    if line[1:3] == " 1 "
 | 
						|
      continue
 | 
						|
    end
 | 
						|
    stacks_row = parse_stacks_line(line)
 | 
						|
    while length(stacks_row) > length(stacks)
 | 
						|
      push!(stacks, [])
 | 
						|
    end
 | 
						|
    for (i, c) in Iterators.enumerate(stacks_row)
 | 
						|
      if c == ' '
 | 
						|
        continue
 | 
						|
      end
 | 
						|
      pushfirst!(stacks[i], c)
 | 
						|
    end
 | 
						|
  end
 | 
						|
  return stacks
 | 
						|
end
 | 
						|
 | 
						|
struct Move
 | 
						|
  count :: Int
 | 
						|
  from :: Int
 | 
						|
  to :: Int
 | 
						|
end
 | 
						|
 | 
						|
function parse_move_line(line)
 | 
						|
  # move 1 from 2 to 1
 | 
						|
  parts = split(line)
 | 
						|
  return Move(parse(Int, parts[2]), parse(Int, parts[4]), parse(Int, parts[6]))
 | 
						|
end
 | 
						|
 | 
						|
function read_apply_moves(stacks, io; rev::Bool = true)
 | 
						|
  for line in eachline(io)
 | 
						|
    move = parse_move_line(line)
 | 
						|
    if rev
 | 
						|
      for i in 1:move.count
 | 
						|
        push!(stacks[move.to], pop!(stacks[move.from]))
 | 
						|
      end
 | 
						|
    else
 | 
						|
      from_len = length(stacks[move.from])
 | 
						|
      from_range = UnitRange(from_len - move.count + 1, from_len)
 | 
						|
      append!(stacks[move.to], splice!(stacks[move.from], from_range))
 | 
						|
    end
 | 
						|
  end
 | 
						|
  return stacks
 | 
						|
end
 | 
						|
 | 
						|
function operate_crane(infile; rev::Bool = true)
 | 
						|
  open(infile, "r") do io
 | 
						|
    stacks = read_stacks(io)
 | 
						|
    stacks2 = read_apply_moves(stacks, io, rev=rev)
 | 
						|
    return stacks2
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
function top_crates(stacks)
 | 
						|
  return join([last(s) for s in stacks])
 | 
						|
end
 | 
						|
 | 
						|
function test()
 | 
						|
  @testset "elf crates 2000" verbose=true begin
 | 
						|
    @test top_crates(operate_crane("example.txt")) == "CMZ"
 | 
						|
    @test top_crates(operate_crane("input.txt")) == "QNHWJVJZW"
 | 
						|
  end
 | 
						|
  @testset "elf crates 2001" verbose=true begin
 | 
						|
    @test top_crates(operate_crane("example.txt", rev=false)) == "MCD"
 | 
						|
    @test top_crates(operate_crane("input.txt", rev=false)) == "BPCZJLFJW"
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
function main()
 | 
						|
  if size(ARGS, 1) == 0
 | 
						|
    test()
 | 
						|
  else
 | 
						|
    infile = ARGS[1]
 | 
						|
    println("infile = ", infile)
 | 
						|
    println("crates: ", read_stacks(infile))
 | 
						|
    stacks2 = operate_crane(infile)
 | 
						|
    println("after : ", stacks2)
 | 
						|
    println("top   : ", top_crates(stacks2))
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
main()
 |