diff --git a/src/main.odin b/src/main.odin index 7ee42e1..6c7f5b3 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,6 +1,7 @@ package rubiks_ga import "core:fmt" +import "core:math/rand" // first, to solve a rubik's cube can mean different things. namely, if i am given a particular // configuration of the cube, and memorize some precomputed steps that takes me to the terminal @@ -60,12 +61,119 @@ import "core:fmt" // be [dynamic; 5]Instruction, but // argh who cares, let's try something - main :: proc() { - x: [dynamic; 5]int - fmt.println(x) - for i in 0 ..< 10 { - append(&x, i) - fmt.println(x) + solution := solved_cube() + defer delete(solution) + arr := [2][4]int{{0, 1, 2, 3}, {4, 5, 6, 7}} + fmt.println(arr) + fmt.println(rotate(arr)) +} + +///////////////////////////////// +/// RUBIKS CUBE STATE MACHINE /// +///////////////////////////////// + +Face :: enum u8 { + Right, + Left, + Up, + Down, + Front, + Back, +} + +Color :: enum u8 { + Red, + Green, + White, + Blue, + Orange, + Yellow, +} + +Cube :: map[Instruction]([3][3]Color) + +solved_cube :: proc(allocator := context.allocator) -> (c: Cube) { + c = make(Cube) + for f in Instruction { + face_colors: [3][3]Color + for i in 0 ..< 3 { + for j in 0 ..< 3 { + switch f { + case .Right: + face_colors[i][j] = .Red + case .Left: + face_colors[i][j] = .Orange + case .Up: + face_colors[i][j] = .White + case .Down: + face_colors[i][j] = .Yellow + case .Front: + face_colors[i][j] = .Green + case .Back: + face_colors[i][j] = .Blue + } + } + } + c[f] = face_colors + } + return +} + +rotate :: proc(arr: [$row][$col]$T) -> (res: [col][row]T) { + for i in 0 ..< row { + for j in 0 ..< col { + res[j][i] = arr[row - 1 - i][j] + } + } + return +} + +// only fundamental instructions; pseudo-instructions only complicate the implementation +Instruction :: distinct Face + +perform_instruction :: proc(c: ^Cube, instr: Face) { + switch instr { + case .Left: + c[.Left] = rotate(c[.Left]) + // TODO: repair + case .Right: + c[.Right] = rotate(c[.Right]) + case .Up: + c[.Up] = rotate(c[.Up]) + case .Down: + c[.Down] = rotate(c[.Down]) + case .Front: + c[.Front] = rotate(c[.Front]) + case .Back: + c[.Back] = rotate(c[.Back]) } } + +///////////////////////// +/// GENETIC ALGORITHM /// +///////////////////////// + +// god's number is 20 for normal notation, 26 for mine. give margin, choose 32 for memory layout +MAX_STEPS :: 32 +POPULATION_SIZE :: 512 + +Chromosome :: [dynamic; MAX_STEPS]Face +Population :: [dynamic; POPULATION_SIZE]Chromosome + +create_population :: proc(size: int) -> (pop: Population) { + for len(pop) < size { + chrom: Chromosome + num_steps := int(rand.norm_float64() * cap(chrom)) + for len(chrom) < num_steps { + i := rand.int_max(len(Face)) + append(&chrom, Face(i)) + } + append(&pop, chrom) + } + return +} + +// TODO: generation step + +// TODO: fitness calculation