2024-11-28 22:08:55 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2024-11-29 15:19:19 +00:00
|
|
|
const Version = "0.1.1"
|
2024-11-28 22:08:55 +00:00
|
|
|
|
|
|
|
type Sudoku struct {
|
|
|
|
Title string
|
|
|
|
Author string
|
|
|
|
Rules string
|
|
|
|
Board [][]int
|
|
|
|
}
|
|
|
|
|
2024-11-29 15:19:19 +00:00
|
|
|
func (sudoku *Sudoku) toBytes() []byte {
|
|
|
|
var bytes []byte
|
|
|
|
bytes = append(bytes, []byte(sudoku.Title)...)
|
|
|
|
bytes = append(bytes, 0)
|
|
|
|
bytes = append(bytes, []byte(sudoku.Author)...)
|
|
|
|
bytes = append(bytes, 0)
|
|
|
|
bytes = append(bytes, []byte(sudoku.Rules)...)
|
|
|
|
bytes = append(bytes, 0)
|
|
|
|
board := boardtoBytes(sudoku.Board)
|
|
|
|
bytes = append(bytes, board...)
|
|
|
|
return bytes
|
|
|
|
}
|
|
|
|
|
|
|
|
func boardtoBytes(boardraw [][]int) []byte {
|
|
|
|
var board []byte
|
|
|
|
var buffer byte
|
|
|
|
for _, row := range boardraw {
|
|
|
|
for _, cell := range row {
|
|
|
|
if cell > 9 || cell < 0 {
|
|
|
|
print(cell, " is not a valid cell value")
|
|
|
|
panic("Invalid cell value")
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Println(cell, buffer)
|
|
|
|
|
|
|
|
if buffer == 0 {
|
|
|
|
buffer = byte(cell)
|
|
|
|
} else {
|
|
|
|
buffer = buffer<<4 | byte(cell)
|
|
|
|
board = append(board, buffer)
|
|
|
|
buffer = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buffer = buffer << 4
|
|
|
|
board = append(board, buffer)
|
|
|
|
return board
|
|
|
|
}
|
|
|
|
|
|
|
|
func bytesToBoard(input []byte) [][]int {
|
|
|
|
var output [][]int
|
|
|
|
row := []int{}
|
|
|
|
|
|
|
|
for _, cell := range input {
|
|
|
|
lower := cell & 0x0F
|
|
|
|
upper := cell >> 4
|
|
|
|
|
|
|
|
row = append(row, int(upper))
|
|
|
|
if len(row) == 9 {
|
|
|
|
rowCopy := make([]int, len(row))
|
|
|
|
copy(rowCopy, row)
|
|
|
|
output = append(output, rowCopy)
|
|
|
|
row = []int{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if lower == 0xF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
row = append(row, int(lower))
|
|
|
|
if len(row) == 9 {
|
|
|
|
rowCopy := make([]int, len(row))
|
|
|
|
copy(rowCopy, row)
|
|
|
|
output = append(output, rowCopy)
|
|
|
|
row = []int{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
|
|
|
func Serialize(sudoku Sudoku) {
|
2024-11-28 22:08:55 +00:00
|
|
|
var serialized []byte
|
|
|
|
var header []byte
|
|
|
|
var body []byte
|
|
|
|
var footer []byte
|
|
|
|
var length uint16
|
|
|
|
|
|
|
|
//HEADER
|
|
|
|
version := getVersion()
|
|
|
|
header = append(header, byte(version>>8), byte(version))
|
|
|
|
|
|
|
|
//BODY
|
2024-11-29 15:19:19 +00:00
|
|
|
body = sudoku.toBytes()
|
2024-11-28 22:08:55 +00:00
|
|
|
|
|
|
|
//FOOTER
|
|
|
|
|
|
|
|
//LENGTH
|
|
|
|
length = uint16(len(header) + 2 + len(body) + len(footer))
|
|
|
|
header = append(header, byte(length>>8), byte(length))
|
|
|
|
|
|
|
|
serialized = append(serialized, header...)
|
|
|
|
serialized = append(serialized, body...)
|
|
|
|
serialized = append(serialized, footer...)
|
|
|
|
os.WriteFile("sudoku.sud", serialized, 0644)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Deserialize() {
|
|
|
|
serialized, err := os.ReadFile("sudoku.sud")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
printBytes(serialized)
|
|
|
|
|
|
|
|
version := uint16(serialized[0])<<8 | uint16(serialized[1])
|
|
|
|
|
|
|
|
if version != getVersion() {
|
|
|
|
printBytes([]byte{byte(version >> 8), byte(version)})
|
|
|
|
println("=/")
|
|
|
|
printBytes([]byte{byte(getVersion() >> 8), byte(getVersion())})
|
|
|
|
panic("Invalid version")
|
|
|
|
}
|
2024-11-29 15:19:19 +00:00
|
|
|
|
|
|
|
body := serialized[4 : len(serialized)-2]
|
|
|
|
board := bytesToBoard(body)
|
|
|
|
fmt.Println(board)
|
2024-11-28 22:08:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getVersion() uint16 {
|
|
|
|
version := strings.Split(Version, ".")
|
|
|
|
|
|
|
|
majorInt, err := strconv.Atoi(version[0])
|
|
|
|
if err != nil || majorInt > 15 {
|
|
|
|
fmt.Println("Invalid major version, the major version must be an integer between 0 and 15")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
major := uint16(majorInt)
|
|
|
|
|
|
|
|
minorInt, err := strconv.Atoi(version[1])
|
|
|
|
if err != nil || minorInt > 15 {
|
|
|
|
fmt.Println("Invalid minor version, the minor version must be an integer between 0 and 15")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
minor := uint16(minorInt)
|
|
|
|
|
|
|
|
patchInt, err := strconv.Atoi(version[2])
|
|
|
|
if err != nil || patchInt > 255 {
|
|
|
|
fmt.Println("Invalid patch version, the patch version must be an integer between 0 and 255")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
patch := uint16(patchInt)
|
|
|
|
|
|
|
|
versionbyte := major<<12 | minor<<8 | patch
|
|
|
|
|
|
|
|
return versionbyte
|
|
|
|
}
|
|
|
|
|
|
|
|
func usedBits(n uint16) int {
|
|
|
|
bits := 0
|
|
|
|
for n > 0 {
|
|
|
|
bits++
|
|
|
|
n >>= 1
|
|
|
|
}
|
|
|
|
return bits
|
|
|
|
}
|
|
|
|
|
|
|
|
func printBytes(bytes []byte) {
|
|
|
|
for _, n := range bytes {
|
|
|
|
fmt.Printf("%08b ", n)
|
|
|
|
fmt.Print("\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2024-11-29 15:19:19 +00:00
|
|
|
sudoku := Sudoku{
|
|
|
|
Title: "Sudoku",
|
|
|
|
Author: "John Doe",
|
|
|
|
Rules: "Fill the board with numbers from 1 to 9",
|
|
|
|
Board: [][]int{
|
|
|
|
{5, 3, 0, 0, 7, 0, 0, 0, 0},
|
|
|
|
{6, 0, 0, 1, 9, 5, 0, 0, 0},
|
|
|
|
{0, 9, 8, 0, 0, 0, 0, 6, 0},
|
|
|
|
{8, 0, 0, 0, 6, 0, 0, 0, 3},
|
|
|
|
{4, 0, 0, 8, 0, 3, 0, 0, 1},
|
|
|
|
{7, 0, 0, 0, 2, 0, 0, 0, 6},
|
|
|
|
{0, 6, 0, 0, 0, 0, 2, 8, 0},
|
|
|
|
{0, 0, 0, 4, 1, 9, 0, 0, 5},
|
|
|
|
{0, 0, 0, 0, 8, 0, 0, 7, 9},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
Serialize(sudoku)
|
2024-11-28 22:08:55 +00:00
|
|
|
Deserialize()
|
2024-11-29 15:19:19 +00:00
|
|
|
}
|
2024-11-28 22:08:55 +00:00
|
|
|
|
2024-11-29 15:19:19 +00:00
|
|
|
/*
|
|
|
|
func clutter(input [][]int) []byte {
|
|
|
|
var output []byte
|
|
|
|
var buffer byte
|
|
|
|
var full bool
|
|
|
|
for _, row := range input {
|
|
|
|
for _, cell := range row {
|
|
|
|
if cell > 9 || cell < 0 {
|
|
|
|
print(cell, " is not a valid cell value")
|
|
|
|
panic("Invalid cell value")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !full {
|
|
|
|
buffer = byte(cell)
|
|
|
|
full = true
|
|
|
|
} else {
|
|
|
|
buffer = buffer<<4 | byte(cell)
|
|
|
|
output = append(output, buffer)
|
|
|
|
buffer = 0
|
|
|
|
full = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if buffer != 0 {
|
|
|
|
buffer = buffer << 4
|
|
|
|
buffer = buffer | 0x0F
|
|
|
|
output = append(output, buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
return output
|
2024-11-28 22:08:55 +00:00
|
|
|
}
|
2024-11-29 15:19:19 +00:00
|
|
|
|
|
|
|
func declutter(input []byte) {
|
|
|
|
var output [][]int
|
|
|
|
row := []int{}
|
|
|
|
|
|
|
|
for _, cell := range input {
|
|
|
|
lower := cell & 0x0F
|
|
|
|
upper := cell >> 4
|
|
|
|
|
|
|
|
row = append(row, int(upper))
|
|
|
|
if len(row) == 9 {
|
|
|
|
rowCopy := make([]int, len(row))
|
|
|
|
copy(rowCopy, row)
|
|
|
|
output = append(output, rowCopy)
|
|
|
|
row = []int{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if lower == 0xF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
row = append(row, int(lower))
|
|
|
|
if len(row) == 9 {
|
|
|
|
rowCopy := make([]int, len(row))
|
|
|
|
copy(rowCopy, row)
|
|
|
|
output = append(output, rowCopy)
|
|
|
|
row = []int{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print("\n")
|
|
|
|
fmt.Println(output)
|
|
|
|
}*/
|