Advertisement
Guest User

Pizza.jl

a guest
Feb 27th, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Julia 4.25 KB | None | 0 0
  1. module Pizza
  2.  
  3. import Base: getindex, setindex!, read, write
  4.  
  5.  
  6.  
  7. struct PizzaInput
  8.     mintopping::Int
  9.     maxsize::Int
  10.     cells::Matrix{Bool}
  11. end
  12. function read(io::IO, ::Type{PizzaInput})
  13.     r,c,l,h = parse.(Int, split(readline(io)))
  14.  
  15.     cells = reduce(vcat, ( [ c == 'T' for i=i:i, c in readline(io)] for i = 1:r) )
  16.  
  17.     return PizzaInput(l,h,cells)
  18. end
  19.  
  20. struct Slice
  21.     row1::Int
  22.     row2::Int
  23.     column1::Int
  24.     column2::Int
  25. end
  26.  
  27. struct WorkingPizza
  28.     input::PizzaInput # reference pizza
  29.     cells::Array{Union{Bool, Nothing}}
  30.     ratio::Float64
  31.  
  32.     WorkingPizza(input::PizzaInput) = new(input, Array{Union{Bool,Nothing}}(input.cells), count(input.cells)/length(input.cells))
  33. end
  34.  
  35. function takeslice!(pizza::WorkingPizza, slice::Slice)
  36.     pizza.cells[slice] = nothing
  37. end
  38.  
  39. function validslice(pizza::WorkingPizza, slice::Slice)
  40.     h,w = size(pizza.cells)
  41.     if !( 1 ≤ slice.row1 ≤ slice.row2 ≤ h && 1 ≤ slice.column1 ≤ slice.column2 ≤ w )
  42.         return false
  43.     end
  44.     sliceCells = pizza.cells[slice]
  45.  
  46.     if length(sliceCells) > pizza.input.maxsize
  47.         return false
  48.     end
  49.  
  50.     tomatos = 0
  51.     for cell in sliceCells
  52.         if cell === nothing
  53.             return false
  54.         end
  55.  
  56.         tomatos += cell
  57.     end
  58.  
  59.     if tomatos < pizza.input.mintopping || length(sliceCells) - tomatos < pizza.input.mintopping
  60.         return false
  61.     end
  62.  
  63.     return true
  64. end
  65.  
  66. getindex(collection::AbstractMatrix, slice::Slice) where T = @view collection[slice.row1:slice.row2, slice.column1:slice.column2]
  67. setindex!(collection::AbstractMatrix, value, slice::Slice) = view(collection, slice.row1:slice.row2, slice.column1:slice.column2) .= value
  68.  
  69. struct PizzaOutput
  70.     slices::Vector{Slice}
  71. end
  72.  
  73. function write(io::IO, output::PizzaOutput)
  74.     println(io, length(output.slices))
  75.     for slice in output.slices
  76.         println(io, "$(slice.row1-1) $(slice.column1-1) $(slice.row2-1) $(slice.column2-1)")
  77.     end
  78. end
  79.  
  80. function tryslice(pizza::WorkingPizza, row, col)
  81.     h,w = size(pizza.cells)
  82.  
  83.     mxsz = min((h - row + 1) * (w - col + 1), pizza.input.maxsize)
  84.     mnsz = 2*pizza.input.mintopping
  85.     for sz = mxsz:-1:mnsz
  86.         f = 1
  87.         while f*f <= sz
  88.             if sz % f == 0
  89.                 g = sz ÷ f
  90.                
  91.                 slice = Slice(row, row+f-1, col, col+g-1)
  92.                 if validslice(pizza, slice)
  93.                     return slice
  94.                 end
  95.  
  96.                 if f ≠ g
  97.                     slice = Slice(row, row+g-1, col, col+f-1)
  98.                     if validslice(pizza, slice)
  99.                         return slice
  100.                     end
  101.                 end
  102.             end
  103.             f += 1
  104.         end
  105.     end
  106.  
  107. end
  108.  
  109. using DataStructures
  110.  
  111. # Random solver
  112. function solve(input::PizzaInput, mxiter = 1000)
  113.     h,w = size(input.cells)
  114.  
  115.     pizza = WorkingPizza(input)
  116.  
  117.     slices = Slice[]
  118.  
  119.     iters = 0
  120.  
  121.     points = Queue{Tuple{Int,Int}}()
  122.     enqueue!(points, (1,1))
  123.  
  124.     i = 0
  125.  
  126.     while !isempty(points) && i < mxiter
  127.         i,j = dequeue!(points)
  128.  
  129.         if pizza.cells[i,j] === nothing
  130.             continue
  131.         end
  132.    
  133.         slice = tryslice(pizza, i, j)
  134.         if slice !== nothing
  135.             push!(slices, slice)
  136.  
  137.             takeslice!(pizza, slice)
  138.  
  139.             slice.row2 < h && enqueue!(points, (slice.row2+1, j))
  140.             slice.column2 < w && enqueue!(points, (i,slice.column2+1))
  141.         else
  142.             i < h && enqueue!(points, (i+1, j))
  143.             j < w && enqueue!(points, (i, j+1))
  144.         end
  145.     end
  146.  
  147.     idx = findfirst(x->x!==nothing,pizza.cells)
  148.  
  149.     while idx !== nothing && i < mxiter
  150.        
  151.         slice = tryslice(pizza, idx[1], idx[2])
  152.         if slice !== nothing
  153.             push!(slices, slice)
  154.             @show slice
  155.             takeslice!(pizza, slice)
  156.         end
  157.  
  158.         idx = findnext(x->x!==nothing,pizza.cells,idx)
  159.  
  160.         i += 1
  161.     end
  162.  
  163.     if !isempty(points)
  164.         @show length(points)
  165.     end
  166.  
  167.     PizzaOutput(slices)
  168. end
  169.  
  170. function score(output::PizzaOutput)
  171.     sum = 0
  172.     for slice in output.slices
  173.         sum += (slice.row2 - slice.row1 + 1) * (slice.column2 - slice.column1 + 1)
  174.     end
  175.     return sum
  176. end
  177.  
  178. function generate_outputs(best = Dict{String, Pair{Int, PizzaOutput}}())
  179.    
  180.     inputs = Dict(file => read(joinpath("inputs", file), Pizza.PizzaInput) for file in readdir("inputs"))
  181.  
  182.     for (file,input) in inputs
  183.         if !haskey(best, file)
  184.             best[file] = 0 => PizzaOutput(Pizza.Slice[])
  185.         end
  186.     end
  187.  
  188.     for (k,input) in inputs
  189.         @show k
  190.         output = solve(input, 10000)
  191.         _score = score(output)
  192.         if _score > first(best[k])
  193.             best[k] = _score => output
  194.             println("$k has new best: $_score")
  195.         end
  196.     end
  197.  
  198.     for (k,(s,o)) in best
  199.         k,_ = splitext(k)
  200.         write("outputs/$k.out", o)
  201.     end
  202.  
  203.     best
  204. end
  205.  
  206. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement