Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,7 @@ atlassian-ide-plugin.xml
/*.log

# oh-my-zsh gradle plugin
.gradletasknamecache
.gradletasknamecache

# Example files
*.out
1,001 changes: 1,001 additions & 0 deletions big.in

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ repositories {

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
testCompile 'junit:junit:4.12'
}
4 changes: 4 additions & 0 deletions example.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3 5 1 6
TTTTT
TMMMT
TTTTT
201 changes: 201 additions & 0 deletions medium.in

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions small.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
6 7 1 5
TMMMTTT
MMMMTMM
TTMTTMT
TMMTMMM
TTTTTTM
TTTTTTM
20 changes: 16 additions & 4 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import model.Pizza
import services.SlicerService
import storage.Store

class Main {
val store = Store()
var slicer = SlicerService()

fun algo () {
val pizza = Pizza(3, 3)
fun main(args: Array<String>) {
todos()
}

fun todos() {
val files = arrayOf("small", "medium", "example", "big")
files.forEach { file ->
run {
val pizza = store.read("$file.in")
val slices = slicer.getSlices(pizza)
println("$file: ${slices.fold(0) { total, next -> total + next.getScore() }}")
store.write("$file.out", slices)
}
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/model/Cell.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package model

data class Cell(val ingredient: String, val used: Boolean)
data class Cell(val ingredient: String, var used: Boolean)
8 changes: 7 additions & 1 deletion src/main/kotlin/model/Slice.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@ package model
data class Slice(val startColumn: Int,
val endColumn: Int,
val startRow: Int,
val endRow: Int)
val endRow: Int) {

fun getScore(): Int {
return ((this.endColumn - this.startColumn) + 1) * ((this.endRow - this.startRow) + 1)
}

}
103 changes: 103 additions & 0 deletions src/main/kotlin/services/SlicerService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package services

import model.Pizza
import model.Slice

class SlicerService {

fun getSlices(pizza: Pizza): List<Slice> {
var slices: MutableList<Slice> = emptyList<Slice>().toMutableList()

for (row in 0..(pizza.R - 1)) {
for (column in 0..(pizza.C - 1)) {
if (!pizza.table[row][column].used) {
val slice = getSliceFrom(pizza, row, column)
if (slice != null) {
slices.add(slice)
}
}
}
}

return slices.map { slice -> getBetterSlice(pizza, slice) }
}

private fun getSliceFrom(pizza: Pizza, row: Int, column: Int): Slice? {
var currentColumn = column
var currentRow = row
var currentSize = 1
var numColumns = 1

while (currentSize <= pizza.H && currentColumn < pizza.C) {
while (currentSize <= pizza.H && currentRow < pizza.R) {
val slice = Slice(column, currentColumn, row, currentRow)
if (checkSlice(slice, pizza)) {
markCellsAsUsed(pizza, row, currentRow, column, currentColumn)
return slice
}
currentRow++
currentSize += numColumns
}
numColumns++
currentSize = numColumns
currentRow = 0
currentColumn++
}

return null
}

private fun getBetterSlice(pizza: Pizza, slice: Slice): Slice {
if (checkSliceSize(slice, pizza.H)) {
var currentColumn = slice.endColumn
var currentRow = slice.endRow + 1
var numColumns = ((slice.endColumn - slice.startColumn) + 1)
var currentSize = numColumns * ((currentRow - slice.startRow) + 1)

while (currentSize <= pizza.H && currentColumn < pizza.C) {
while (currentSize <= pizza.H && currentRow < pizza.R) {
val betterSlice = Slice(slice.startColumn, currentColumn, slice.startRow, currentRow)
if (checkSlice(betterSlice, pizza)) {
markCellsAsUsed(pizza, betterSlice.startRow, currentRow, betterSlice.startColumn, currentColumn)
return betterSlice
}
currentRow++
currentSize += numColumns
}
numColumns++
currentSize = numColumns
currentRow = 0
currentColumn++
}
}

return slice
}

private fun checkSlice(slice: Slice, pizza: Pizza): Boolean =
checkSliceIngredients(slice, pizza) && checkSliceSize(slice, pizza.H)

private fun checkSliceSize(slice: Slice, H: Int): Boolean =
((slice.endColumn - slice.startColumn) + 1) * ((slice.endRow - slice.startRow) + 1) <= H

private fun checkSliceIngredients(slice: Slice, pizza: Pizza): Boolean {
var mushrooms = 0
var tomatoes = 0
for (row in slice.startRow..slice.endRow) {
for (column in slice.startColumn..slice.endColumn) {
if (pizza.table[row][column].ingredient.equals("M")) mushrooms++ else tomatoes++
}
}

return tomatoes >= pizza.L && mushrooms >= pizza.L
}

private fun markCellsAsUsed(pizza: Pizza, startingRow: Int, endingRow: Int, startingColumn: Int, endingColumn: Int) {
for (row in startingRow..endingRow) {
for (column in startingColumn..endingColumn) {
pizza.table[row][column].used = true
}
}
}

}
43 changes: 43 additions & 0 deletions src/main/kotlin/storage/Store.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package storage

import model.Cell
import model.Pizza
import model.Slice
import java.io.File
import java.util.*

class Store {

fun read(fileName: String): Pizza {

val scanner = Scanner(File(fileName))

val R = scanner.nextInt()
val C = scanner.nextInt()
val L = scanner.nextInt()
val H = scanner.nextInt()
scanner.nextLine()

val pizza = Array(R) { index ->
var line = scanner.nextLine()

val row = Array(C) { index ->
Cell(line[index].toString(), false)
}

row
}

return Pizza(pizza, R, C, L, H)
}

fun write(fileName: String, slices: List<Slice>) {
File("$fileName").printWriter().use { out ->
out.println("${slices.size}")
slices.forEach { slice ->
out.println("${slice.startRow} ${slice.startColumn} ${slice.endRow} ${slice.endColumn}")
}
}
}

}
86 changes: 86 additions & 0 deletions src/test/kotlin/storage/StoreTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package storage

import model.Cell
import model.Pizza
import org.hamcrest.core.Is.`is`
import org.junit.Assert.assertThat
import org.junit.Test

/**

3 4 1 5
TMMM
MMMM
TTTM

*/
class StoreShould {

private fun pizza(): Pizza {
val store = Store()
val pizza = store.read("src/test.in")
return pizza
}

@Test
fun `read a pizza row information`() {
val pizza = pizza()

assertThat(pizza.R, `is`(3))
}

@Test
fun `read a pizza column information`() {
val pizza = pizza()

assertThat(pizza.C, `is`(4))
}

@Test
fun `read a pizza min ingredients per slice information`() {
val pizza = pizza()

assertThat(pizza.L, `is`(1))
}

@Test
fun `read a pizza max ingredients per slice information`() {
val pizza = pizza()

assertThat(pizza.H, `is`(5))
}

@Test
fun `read a pizza table information`() {
val pizza = pizza().table

val expectedPizza = Array(3) { index ->
getExpectedPizzaRow(index)
}

assertThat(pizza.size, `is`(expectedPizza.size))
assertThat(pizza, `is`(expectedPizza))
}

/**
* TMMM
* MMMM
* TTTM
*/
private fun getExpectedPizzaRow(index: Int): Array<Cell> {
val firstRow = arrayOf(T(), M(), M(), M())
val secondRow = arrayOf(M(), M(), M(), M())
val thirdRow = arrayOf(T(), T(), T(), M())

return when (index) {
0 -> firstRow
1 -> secondRow
2 -> thirdRow
else -> firstRow
}
}

private fun M() = Cell("M", false)

private fun T() = Cell("T", false)
}