Skip to content

Instantly share code, notes, and snippets.

@hikaMaeng
Created April 16, 2025 15:06
Show Gist options
  • Save hikaMaeng/8605f42a60983737a0d58d6b4596f016 to your computer and use it in GitHub Desktop.
Save hikaMaeng/8605f42a60983737a0d58d6b4596f016 to your computer and use it in GitHub Desktop.
package org.example
//fun Int.collatz():List<Int> = collatz1(listOf())
//private tailrec fun Int.collatz1(acc:List<Int>):List<Int>
//= when {
// this == 1->acc + this
// this % 2 == 0->(this / 2).collatz1(acc + this)
// else->(this * 3 + 1).collatz1(acc + this)
//}
fun Int.collatz2():List<Int> = collatz2(this, listOf())
private tailrec fun collatz2(v:Int, acc:List<Int>):List<Int>
= when {
v == 1->acc + v
v % 2 == 0->collatz2(v / 2, acc + v)
else->collatz2(v * 3 + 1, acc + v)
}
fun q5_1(){
println(13.collatz2())
}
package org.example
import org.example.Direction.Down
import org.example.Direction.Up
data class Elevator(val floor:Int)
//sealed interface Direction
//data object Up : Direction
//data object Down : Direction
enum class Direction {
Up, Down
}
fun List<Direction>.fold(acc:Elevator, block:(Elevator, Direction)->Elevator): Elevator
= fold2(this, acc, block, 0)
private tailrec fun <ITEM, ACC> fold2(
list:List<ITEM>, acc:ACC, block:(ACC, ITEM)->ACC, cursor:Int
): ACC
= if (cursor == list.size) acc else fold2(list, block(acc, list[cursor]), block, cursor + 1)
fun q5_2(){
val list = listOf(Up, Up, Down, Up, Down, Down, Up, Up, Up, Down)
val elevator = list.fold(Elevator(0)) { acc, direction ->
when (direction) {
Up -> Elevator(acc.floor + 1)
Down -> Elevator(acc.floor - 1)
}
}
println("Elevator is at floor ${elevator.floor} == 2")
}
package org.example
sealed class JsonCompactor(
val original: String,
cursor: Int,
val compacted:StringBuilder,
){
companion object{
tailrec fun compactJson(target:JsonCompactor):JsonCompactor {
val nextCursor = target.cursor
return if(nextCursor < target.original.length) compactJson(target.compact(target.original[nextCursor])) else target
}
}
val cursor = cursor + 1
protected abstract fun compact(c:Char):JsonCompactor
}
class OutQuotes(original:String, cursor:Int, compacted:StringBuilder):JsonCompactor(original, cursor, compacted){
override fun compact(c:Char):JsonCompactor = when(c){
'"' -> InQuotes(original, cursor, compacted.apply{append(c)})
' ', '\t', '\r', '\n' -> OutQuotes(original, cursor, compacted)
else -> OutQuotes(original, cursor, compacted.apply{append(c)})
}
}
class InQuotes(original:String, cursor:Int, compacted:StringBuilder):JsonCompactor(original, cursor, compacted){
override fun compact(c:Char):JsonCompactor = when(c){
'"' -> OutQuotes(original, cursor, compacted.apply{append(c)})
'\\' -> Escaped(original, cursor, compacted.apply{append(c)})
else -> InQuotes(original, cursor, compacted.apply{append(c)})
}
}
class Escaped(original:String, cursor:Int, compacted:StringBuilder):JsonCompactor(original, cursor, compacted){
override fun compact(c:Char):JsonCompactor
= InQuotes(original, cursor, compacted.apply{append(c)})
}
fun String.compactJson():String
= StringBuilder().also{JsonCompactor.compactJson(OutQuotes(this, -1, it))}.toString()
enum class Type{OUT_QUOTES, IN_QUOTES, ESCAPED}
fun String.compactJson2():String
= fold(StringBuilder() to Type.OUT_QUOTES){(builder, type), c->
when(type) {
Type.OUT_QUOTES->builder.apply {
if(c !in " \t\r\n") append(c)
} to if(c == '"') Type.IN_QUOTES else type
Type.IN_QUOTES->builder.append(c) to when(c) {
'"'->Type.OUT_QUOTES
'\\'->Type.ESCAPED
else->type
}
Type.ESCAPED->builder.append(c) to Type.IN_QUOTES
}
}.first.toString()
fun q5_3(){
println("q5_3")
val json = """{ "my greetings" : "hello world! \"How arg you>\"" }"""
val compact = """{"my greetings":"hello world! \"How arg you>\""}"""
println("${json.compactJson()} == $compact ? ${json.compactJson() == compact}")
println("${json.compactJson2()} == $compact ? ${json.compactJson2() == compact}")
}
package org.example
/**
* algebra : 대수 - 구체적인 수의 연산과 성질 덧셈, 뺄샘, 곱셈, 나눗셈 연산 - 구상수 자연수, 정수, 유리수, 실수 ->방정식, 유도식, 인수분해
* abstract algebra : 추상 대수는 연산의 성질만 일치한다면 어떤 구상수가 와도 연산은 성립해
* 불린대수 추상대수 구상대수: true, false안중요. 0,1대체해도 상관없음. 부정, 앤드, 오알 이라는 연산의 교환분배법칙 및 항등원
*
* 추상대수론에는 일반화된 연산의 성질 -> 집합론
*
* ZSF집합론 : 원소가 집합에 속해있고 교집합 차집합... 원소에 관심이 많다. 집합에 원소가 속했있다에 관심
* 추상대수집합론 : 원소란 이항연산으로 정의된다 - (A, A)->A A를 집합 +(자연수, 자연수) -> 자연수 자연수를 덧셈이항연산의 집합으로 볼래
* {0,1,2,3} "% 4"
* 1. 가장 원시적인 추상대수집합은 (A, A)->A 라는 이항연산이 있음. A->A = f(A, A):A
* 2. 이항연산이 결합법칙을 성립시킨다 f(f(a, b), c) = f(a, f(b, c)) -> 연산을 합성시킬 수 있다 -> 연산만 합성을 반복시켜 연산 가능성만
* 나타내도 실제 게산 결과와 일치하는게 성립 = 참조투명성 = 함수합성이 여러 계산을 합친 계산으로 만들어지고 실제 계산은 안해
* 추상대수학은 계산결과에 관심이 없다. 연산과 연산의 성질에 관심이 있다.
* 추상대수의 모든 연산에서 가장 중요한것 - 결합성이 확보되야 최소조건이 달성됨
* 이항연산이 결합성을 만족하는 성질이 잇을 때 ----> 반군 세미그룹
* 반군의 이항연산이 항등원을 갖고 있다면 --> 모노이드
* 모노이드의 이항연산이 역원을 갖고 있다면 --> 군 그룹
* 군 혹은 모노이드 까지의 이항연산은 일반적으로 곱이라 부른다.
* 보통 군을 곱이라는 연산 하나를 갖고 잇는 집합이라
* 이항연산이 교환법칙마져 만족하면 ->아벨군
* 군체환론 group(곱연산 하나) ring(곱연산과덧셈연산이 분배법칙을 성립시킬때) field(환의 연산이 역원을 성립시킬떄)
*/
interface Monoid<T> {
val id: T
fun combine(a: T, b: T): T
fun lawAssociativity(a: T, b: T, c: T): Boolean = combine(a, combine(b, c)) == combine(combine(a, b), c)
}
fun <T> List<T>.fold(monoid:Monoid<T>):T = this.fold(monoid.id) { acc, item -> monoid.combine(acc, item) }
fun q5_4(){
val intPlusMonoid = object : Monoid<Int> {
override val id = 0
override fun combine(a: Int, b: Int) = a + b
}
println(listOf(1,2,3).fold(intPlusMonoid))
}
package org.example
import org.example.ElevatorState.Closed
import org.example.ElevatorState.Opened
import kotlin.math.abs
sealed interface ElevatorState {
enum class Direction { UP, DOWN, NONE }
val direction: Direction
val floor:Int
val objects:Set<Int>
data class Closed(override val direction:Direction, override val floor:Int, override val objects:Set<Int>): ElevatorState
data class Opened(override val direction:Direction, override val floor:Int, override val objects:Set<Int>): ElevatorState
}
sealed interface ElevatorCommand:(ElevatorState)->ElevatorState{
fun handle(state:ElevatorState):List<ElevatorEvent>
data object Close:ElevatorCommand{
override fun invoke(state: ElevatorState): ElevatorState = when (state) {
is Closed -> state
is Opened -> Closed(state.direction, state.floor, state.objects)
}
override fun handle(state: ElevatorState): List<ElevatorEvent> = when (state) {
is Closed -> listOf()
is Opened -> listOf(ElevatorEvent.Closed(true))
}
}
data class Call(val floor:Int, val direction: ElevatorState.Direction):ElevatorCommand{
override fun invoke(state: ElevatorState): ElevatorState = when (state) {
is Closed -> if(state.floor == floor && (state.direction == direction || state.direction == ElevatorState.Direction.NONE))
Opened(state.direction, floor, state.objects) else state.copy(objects = state.objects + floor)
is Opened -> state.copy(objects = state.objects + floor)
}
override fun handle(state: ElevatorState): List<ElevatorEvent> = when (state) {
is Closed -> if(state.floor == floor && (state.direction == direction || state.direction == ElevatorState.Direction.NONE)){
listOf(ElevatorEvent.Opened(false), ElevatorEvent.FloorChanged(state.floor, floor))
} else listOf(ElevatorEvent.ObjectsAdded(floor))
is Opened -> listOf(ElevatorEvent.ObjectsAdded(floor))
}
}
data class Move(val floor:Int):ElevatorCommand{
override fun invoke(state: ElevatorState): ElevatorState = when (state) {
is Closed -> if (state.floor == floor) Opened(state.direction, floor, state.objects) else state.copy(objects = state.objects + floor)
is Opened -> if (state.floor == floor) state else state.copy(objects = state.objects + floor)
}
override fun handle(state: ElevatorState): List<ElevatorEvent> = when (state) {
is Closed -> if (state.floor == floor) listOf(ElevatorEvent.Opened(false), ElevatorEvent.FloorChanged(state.floor, floor))
else listOf(ElevatorEvent.ObjectsAdded(floor))
is Opened -> if (state.floor == floor) listOf() else listOf(ElevatorEvent.ObjectsAdded(floor))
}
}
data object Step:ElevatorCommand{
override fun handle(state: ElevatorState): List<ElevatorEvent> = listOf()
override fun invoke(state: ElevatorState): ElevatorState = when (state) {
is Opened -> state // 문이 열려 있으면 이동 불가
is Closed -> {
if(state.objects.isEmpty()) state.copy(direction = ElevatorState.Direction.NONE)
else {
val current = state.floor
val objects = state.objects
val dir = when(state.direction) {
ElevatorState.Direction.NONE-> {
val next = objects.minByOrNull {abs(it - current)}!!
if(next > current) ElevatorState.Direction.UP else ElevatorState.Direction.DOWN
}
else->state.direction
}
val floor = when(dir) {
ElevatorState.Direction.UP->state.floor + 1
ElevatorState.Direction.DOWN->state.floor - 1
ElevatorState.Direction.NONE->state.floor
}
if(floor in objects) {
val remaining = objects - floor
Opened(when {
remaining.isEmpty() -> ElevatorState.Direction.NONE
dir == ElevatorState.Direction.UP -> if(remaining.any { it > floor }) ElevatorState.Direction.UP else ElevatorState.Direction.DOWN
dir == ElevatorState.Direction.DOWN -> if(remaining.any { it < floor }) ElevatorState.Direction.DOWN else ElevatorState.Direction.UP
else -> ElevatorState.Direction.NONE
}, floor, remaining)
}else state.copy(dir, floor, objects)
}
}
}
}
}
fun q6_1() {
var state: ElevatorState = ElevatorState.Closed(
direction = ElevatorState.Direction.NONE,
floor = 3,
objects = emptySet()
)
val scenario: List<Pair<String, ElevatorCommand>> = listOf(
"콜: 5층에서 아래로" to ElevatorCommand.Call(5, ElevatorState.Direction.DOWN),
"스텝 실행" to ElevatorCommand.Step,
"콜: 2층에서 위로" to ElevatorCommand.Call(2, ElevatorState.Direction.UP),
"스텝 실행" to ElevatorCommand.Step,
"문 닫기" to ElevatorCommand.Close,
"이동: 1층으로 Move" to ElevatorCommand.Move(1),
"스텝 실행" to ElevatorCommand.Step,
"스텝 실행" to ElevatorCommand.Step,
"스텝 실행" to ElevatorCommand.Step,
"스텝 실행" to ElevatorCommand.Step,
"문 닫기" to ElevatorCommand.Close,
"이동: 3층으로 Move" to ElevatorCommand.Move(3),
"스텝 실행" to ElevatorCommand.Step,
"문 닫기" to ElevatorCommand.Close,
"스텝 실행" to ElevatorCommand.Step,
"스텝 실행" to ElevatorCommand.Step,
"문 닫기" to ElevatorCommand.Close,
)
scenario.forEachIndexed { index, (label, cmd) ->
println("[$index] $label, $cmd")
state = cmd(state)
println(" → 전이상태: $state")
}
}
package org.example
import kotlin.collections.fold
sealed interface ElevatorEvent:(ElevatorState)->ElevatorState{
data object Idle : ElevatorEvent{
override fun invoke(e:ElevatorState): ElevatorState = e
}
data class Opened(val isOpened:Boolean):ElevatorEvent{
override fun invoke(e:ElevatorState): ElevatorState = ElevatorState.Opened(e.direction, e.floor, e.objects)
}
data class Closed(val isOpened:Boolean):ElevatorEvent{
override fun invoke(e:ElevatorState): ElevatorState = ElevatorState.Closed(e.direction, e.floor, e.objects)
}
data class FloorChanged(val from: Int, val to: Int) : ElevatorEvent{
override fun invoke(e:ElevatorState): ElevatorState = when (e) {
is ElevatorState.Closed -> e.copy(floor = to)
is ElevatorState.Opened -> e.copy(floor = to)
}
}
data class ObjectsAdded(val floor: Int) : ElevatorEvent{
override fun invoke(e:ElevatorState): ElevatorState = when (e) {
is ElevatorState.Closed -> e.copy(objects = e.objects + floor)
is ElevatorState.Opened -> e.copy(objects = e.objects + floor)
}
}
data class ObjectsRemoved(val floor: Int) : ElevatorEvent{
override fun invoke(e:ElevatorState): ElevatorState = when (e) {
is ElevatorState.Closed -> e.copy(objects = e.objects - floor)
is ElevatorState.Opened -> e.copy(objects = e.objects - floor)
}
}
}
//[e,e,e,e]->s
//s +[e,e,e,e,e,e,e,e,e,e,e,e] -> s
//[e,e,e,e] == s + [e,e,e,e,e] ->s + [e,e,e] -> s
fun List<ElevatorEvent>.replay(snapshot:ElevatorState):ElevatorState
= fold(snapshot){acc, event->event(acc)}
fun ElevatorState.handle(vararg command:ElevatorCommand):List<ElevatorEvent>
= command.fold(listOf<List<ElevatorEvent>>()){acc, command->
acc + command.handle(acc.flatten().replay(this))
acc
}.flatten()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment