This commit is contained in:
		
							parent
							
								
									0f2b85f2ad
								
							
						
					
					
						commit
						7a1dba17f1
					
				
							
								
								
									
										136
									
								
								day12.kts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										136
									
								
								day12.kts
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,136 @@
 | 
			
		||||
#!/usr/bin/env kotlin
 | 
			
		||||
import java.util.Scanner
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
val scanner = Scanner(System.`in`)
 | 
			
		||||
 | 
			
		||||
class Map(private val grid: List<List<String>>) {
 | 
			
		||||
    private val fields = mutableSetOf<Field>()
 | 
			
		||||
    private val map = mutableListOf<List<Plot>>()
 | 
			
		||||
    init {
 | 
			
		||||
        for ((y, line) in grid.withIndex()) {
 | 
			
		||||
            map.add(line.mapIndexed { x, s -> Plot(Pair(x, y), s) })
 | 
			
		||||
        }
 | 
			
		||||
        for (y in 0 until this.getHeight()) {
 | 
			
		||||
            for (x in 0 until this.getWidth()) {
 | 
			
		||||
                val plot = getPlot(x, y)
 | 
			
		||||
                if (!plot.hasField()) {
 | 
			
		||||
                    val field = Field(this)
 | 
			
		||||
                    plot.addField(field)
 | 
			
		||||
                    fields.add(field)
 | 
			
		||||
                    field.expand(plot)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fun getWidth(): Int = grid[0].size
 | 
			
		||||
    fun getHeight(): Int = grid.size
 | 
			
		||||
    fun getPlot(x: Int, y: Int): Plot = map[y][x]
 | 
			
		||||
 | 
			
		||||
    fun getFields(): Set<Field> = fields
 | 
			
		||||
 | 
			
		||||
    fun getPrice(): Long = fields.sumOf { it.getPrice() }
 | 
			
		||||
    fun getBulkPrice(): Long = fields.sumOf { it.getBulkPrice() }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Field(private val map: Map) {
 | 
			
		||||
    private val fieldPlots = mutableSetOf<Plot>()
 | 
			
		||||
    private val borderPlots = mutableSetOf<Pair<Plot, Plot>>()
 | 
			
		||||
    fun addPlot(plot: Plot) {
 | 
			
		||||
        fieldPlots.add(plot)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun expand(plot: Plot) {
 | 
			
		||||
        val (x, y) = plot.getPosition()
 | 
			
		||||
        val checkPositions = listOf(Pair(x - 1, y), Pair(x + 1, y), Pair(x, y - 1), Pair(x, y + 1))
 | 
			
		||||
        for ((checkX, checkY) in checkPositions) {
 | 
			
		||||
            if (checkX < 0 || checkX >= map.getWidth() || checkY < 0 || checkY >= map.getHeight()) {
 | 
			
		||||
                addBorder(plot, Plot(Pair(checkX, checkY), "."))
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
            val checkedPlot = map.getPlot(checkX, checkY)
 | 
			
		||||
            if (plot.getType() == checkedPlot.getType()) {
 | 
			
		||||
                if (!checkedPlot.hasField()) {
 | 
			
		||||
                    checkedPlot.addField(this)
 | 
			
		||||
                    expand(checkedPlot)
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                addBorder(plot, checkedPlot)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun addBorder(plot: Plot, checkedPlot: Plot) {
 | 
			
		||||
        borderPlots.add(Pair(plot, checkedPlot))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getPrice(): Long {
 | 
			
		||||
        return getArea() * getCircumference()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getArea(): Long = fieldPlots.size.toLong()
 | 
			
		||||
    fun getCircumference(): Long = borderPlots.size.toLong()
 | 
			
		||||
    fun getBulkPrice(): Long {
 | 
			
		||||
        return getArea() * getNumberOfSides()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getNumberOfSides(): Long {
 | 
			
		||||
        val leftBorders = borderPlots.filter { it.first.getPosition().first > it.second.getPosition().first}.map { it.first.getPosition() }
 | 
			
		||||
        val rightBorders = borderPlots.filter { it.first.getPosition().first < it.second.getPosition().first}.map { it.first.getPosition() }
 | 
			
		||||
        val topBorders = borderPlots.filter { it.first.getPosition().second > it.second.getPosition().second}.map { it.first.getPosition() }
 | 
			
		||||
        val bottomBorders = borderPlots.filter { it.first.getPosition().second < it.second.getPosition().second}.map { it.first.getPosition() }
 | 
			
		||||
 | 
			
		||||
        return countSides(leftBorders) + countSides(rightBorders) + countSides(topBorders) + countSides(bottomBorders)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun countSides(coordinates: List<Pair<Int, Int>>): Long {
 | 
			
		||||
        val visited = mutableSetOf<Pair<Int, Int>>()
 | 
			
		||||
        val coordinateSet = coordinates.toSet()
 | 
			
		||||
        var sideCount = 0
 | 
			
		||||
        val directions = listOf(Pair(1, 0), Pair(0, 1), Pair(-1, 0), Pair(0, -1))
 | 
			
		||||
 | 
			
		||||
        fun dfs(coord: Pair<Int, Int>) {
 | 
			
		||||
            val stack = mutableListOf(coord)
 | 
			
		||||
            while (stack.isNotEmpty()) {
 | 
			
		||||
                val current = stack.removeLast()
 | 
			
		||||
                if (current in visited) continue
 | 
			
		||||
                visited.add(current)
 | 
			
		||||
                directions.map { (dx, dy) -> Pair(current.first + dx, current.second + dy) }
 | 
			
		||||
                    .filter { it in coordinateSet && it !in visited }
 | 
			
		||||
                    .forEach { stack.add(it) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (coord in coordinates) {
 | 
			
		||||
            if (coord !in visited) {
 | 
			
		||||
                sideCount++
 | 
			
		||||
                dfs(coord)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return sideCount.toLong()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Plot(private val position: Pair<Int, Int>, private val type: String) {
 | 
			
		||||
    private var field: Field? = null
 | 
			
		||||
    fun addField(field: Field) {
 | 
			
		||||
        this.field = field
 | 
			
		||||
        field.addPlot(this)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun hasField(): Boolean = field != null
 | 
			
		||||
    fun getPosition(): Pair<Int, Int> = position
 | 
			
		||||
    fun getType(): String = type
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val grid = mutableListOf<List<String>>()
 | 
			
		||||
while (scanner.hasNextLine()) {
 | 
			
		||||
    grid.add(scanner.nextLine().split("").filter { it.isNotEmpty() })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val map = Map(grid.reversed())
 | 
			
		||||
println("The price is: ${map.getPrice()}")
 | 
			
		||||
println("The bulk price is ${map.getBulkPrice()}")
 | 
			
		||||
							
								
								
									
										2
									
								
								day12.kts.testvalue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								day12.kts.testvalue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
The price is: 1375476
 | 
			
		||||
The bulk price is 821372
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user