SUD/v1/sud.go
2024-11-29 16:19:19 +01:00

270 lines
5.1 KiB
Go

package main
import (
"fmt"
"os"
"strconv"
"strings"
)
const Version = "0.1.1"
type Sudoku struct {
Title string
Author string
Rules string
Board [][]int
}
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) {
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
body = sudoku.toBytes()
//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")
}
body := serialized[4 : len(serialized)-2]
board := bytesToBoard(body)
fmt.Println(board)
}
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() {
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)
Deserialize()
}
/*
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
}
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)
}*/