This commit is contained in:
2026-06-19 07:25:46 +03:00
parent 06823ee547
commit 2d73ce1727
52 changed files with 5173 additions and 547 deletions

View File

@@ -6,9 +6,11 @@ import (
"math"
"slices"
"testing"
"time"
bin "gordenko.dev/dima/bin/little"
"gordenko.dev/dima/qb"
"gordenko.dev/dima/textutil"
)
func equalFloatSlices(a, b []float64, epsilon float64) bool {
@@ -21,23 +23,23 @@ func equalFloatSlices(a, b []float64, epsilon float64) bool {
var (
cumulativeTestCases = []struct {
Nums []float64
Name string
Offset int
ChangeSize int
Buf []byte
BaseValue float64
LastDelta uint64
Nums []float64
Name string
RewindOffset int
ChangeSize int
Buf []byte
BaseValue float64
LastDelta uint64
}{
{
Nums: []float64{
0,
},
Name: "add 1st value zero",
Offset: 0,
ChangeSize: 3,
Name: "add 1st value zero",
RewindOffset: 0,
ChangeSize: 3,
Buf: []byte{
0x8f, // base value
0x80, // base value
0x80, // delta 0
0x80, // literal (len = 1)
0x00, 0x00, 0x00, 0x00, 0x00,
@@ -49,9 +51,9 @@ var (
Nums: []float64{
1.5,
},
Name: "add 1st value non zero",
Offset: 0,
ChangeSize: 3,
Name: "add 1st value non zero",
RewindOffset: 0,
ChangeSize: 3,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -66,9 +68,9 @@ var (
1.5,
1.5,
},
Name: "literal switch to run",
Offset: 1,
ChangeSize: 1,
Name: "literal switch to run",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -84,9 +86,9 @@ var (
1.6,
1.6,
},
Name: "literal decrease by 1 and switch to run",
Offset: 2,
ChangeSize: 3,
Name: "literal decrease by 1 and switch to run",
RewindOffset: 2,
ChangeSize: 3,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -104,9 +106,9 @@ var (
1.5,
1.5,
},
Name: "increment run",
Offset: 1,
ChangeSize: 1,
Name: "increment run",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -123,9 +125,9 @@ var (
1.5,
1.6,
},
Name: "run switch to literal",
Offset: 0,
ChangeSize: 2,
Name: "run switch to literal",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -138,10 +140,10 @@ var (
LastDelta: 1,
},
{
Nums: repeatFloat64(1.5, 129),
Name: "increment run to full fill h-byte",
Offset: 1,
ChangeSize: 1,
Nums: repeatFloat64(1.5, 129),
Name: "increment run to full fill h-byte",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -152,10 +154,10 @@ var (
LastDelta: 0,
},
{
Nums: repeatFloat64(1.5, 130),
Name: "run switch to literal after h-byte overflow",
Offset: 0,
ChangeSize: 2,
Nums: repeatFloat64(1.5, 130),
Name: "run switch to literal after h-byte overflow",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -173,9 +175,9 @@ var (
1.6,
1.7,
},
Name: "increment literal",
Offset: 1,
ChangeSize: 2,
Name: "increment literal",
RewindOffset: 1,
ChangeSize: 2,
Buf: []byte{
0x8f, // base value
0x80, // delta 0
@@ -203,11 +205,11 @@ func TestCumulativeDeltaCompressor(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report = c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
if report.Offset != testCase.Offset {
if report.RewindOffset != testCase.RewindOffset {
t.Fatalf("%s: got offset %d are not equal expected %d",
testCase.Name, report.Offset, testCase.Offset)
testCase.Name, report.RewindOffset, testCase.RewindOffset)
}
if report.ChangeSize != testCase.ChangeSize {
t.Fatalf("%s: got changeSize %d are not equal expected %d",
@@ -241,7 +243,7 @@ func TestRestoreCumulativeDeltaCompressor(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report = c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
restored := NewValueDeltaCompressor(metricType, fracDigits, buf, c.Size())
@@ -270,7 +272,7 @@ func TestCumulativeDeltaDecompressorFromState(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report := c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
d := c.CreateDecompressor(metricType, fracDigits)
@@ -304,7 +306,7 @@ func TestCumulativeDeltaDecompressorFromEnd(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report := c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
d := NewValueDeltaDecompressor(metricType, fracDigits)
@@ -330,21 +332,21 @@ func TestCumulativeDeltaDecompressorFromEnd(t *testing.T) {
var (
instantTestCases = []struct {
Nums []float64
Name string
Offset int
ChangeSize int
Buf []byte
BaseValue float64
LastDelta uint64
Nums []float64
Name string
RewindOffset int
ChangeSize int
Buf []byte
BaseValue float64
LastDelta uint64
}{
{
Nums: []float64{
1.5,
},
Name: "add 1st value",
Offset: 0,
ChangeSize: 3,
Name: "add 1st value",
RewindOffset: 0,
ChangeSize: 3,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -358,9 +360,9 @@ var (
Nums: []float64{
-1.5,
},
Name: "add 1st value (negative)",
Offset: 0,
ChangeSize: 3,
Name: "add 1st value (negative)",
RewindOffset: 0,
ChangeSize: 3,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -375,9 +377,9 @@ var (
1.5,
1.5,
},
Name: "literal switch to run",
Offset: 1,
ChangeSize: 1,
Name: "literal switch to run",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -392,9 +394,9 @@ var (
-1.5,
-1.5,
},
Name: "literal switch to run (negative)",
Offset: 1,
ChangeSize: 1,
Name: "literal switch to run (negative)",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -410,9 +412,9 @@ var (
1.6,
1.6,
},
Name: "literal decrease by 1 and switch to run",
Offset: 2,
ChangeSize: 3,
Name: "literal decrease by 1 and switch to run",
RewindOffset: 2,
ChangeSize: 3,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -430,9 +432,9 @@ var (
-1.6,
-1.6,
},
Name: "literal decrease by 1 and switch to run (negative)",
Offset: 2,
ChangeSize: 3,
Name: "literal decrease by 1 and switch to run (negative)",
RewindOffset: 2,
ChangeSize: 3,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -450,9 +452,9 @@ var (
1.4,
1.4,
},
Name: "literal decrease by 1 and switch to run (negative delta)",
Offset: 2,
ChangeSize: 3,
Name: "literal decrease by 1 and switch to run (negative delta)",
RewindOffset: 2,
ChangeSize: 3,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -470,9 +472,9 @@ var (
-1.4,
-1.4,
},
Name: "literal decrease by 1 and switch to run (positive delta, negative)",
Offset: 2,
ChangeSize: 3,
Name: "literal decrease by 1 and switch to run (positive delta, negative)",
RewindOffset: 2,
ChangeSize: 3,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -490,9 +492,9 @@ var (
1.5,
1.5,
},
Name: "increment run",
Offset: 1,
ChangeSize: 1,
Name: "increment run",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -508,9 +510,9 @@ var (
-1.5,
-1.5,
},
Name: "increment run (negative)",
Offset: 1,
ChangeSize: 1,
Name: "increment run (negative)",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -527,9 +529,9 @@ var (
1.5,
1.6,
},
Name: "run switch to literal",
Offset: 0,
ChangeSize: 2,
Name: "run switch to literal",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -548,9 +550,9 @@ var (
-1.5,
-1.6,
},
Name: "run switch to literal (negative)",
Offset: 0,
ChangeSize: 2,
Name: "run switch to literal (negative)",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -569,9 +571,9 @@ var (
1.5,
1.4,
},
Name: "run switch to literal (negative delta)",
Offset: 0,
ChangeSize: 2,
Name: "run switch to literal (negative delta)",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -590,9 +592,9 @@ var (
-1.5,
-1.4,
},
Name: "run switch to literal (positive delta, negative version)",
Offset: 0,
ChangeSize: 2,
Name: "run switch to literal (positive delta, negative version)",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -605,10 +607,10 @@ var (
LastDelta: bin.EncodeZigZag(1),
},
{
Nums: repeatFloat64(1.5, 129),
Name: "increment run to full fill h-byte",
Offset: 1,
ChangeSize: 1,
Nums: repeatFloat64(1.5, 129),
Name: "increment run to full fill h-byte",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -619,10 +621,10 @@ var (
LastDelta: 0,
},
{
Nums: repeatFloat64(-1.5, 129),
Name: "increment run to full fill h-byte (negative version)",
Offset: 1,
ChangeSize: 1,
Nums: repeatFloat64(-1.5, 129),
Name: "increment run to full fill h-byte (negative version)",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -633,10 +635,10 @@ var (
LastDelta: 0,
},
{
Nums: repeatFloat64(1.5, 130),
Name: "run switch to literal after h-byte overflow",
Offset: 0,
ChangeSize: 2,
Nums: repeatFloat64(1.5, 130),
Name: "run switch to literal after h-byte overflow",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -649,10 +651,10 @@ var (
LastDelta: 0,
},
{
Nums: repeatFloat64(-1.5, 130),
Name: "run switch to literal after h-byte overflow (negative version)",
Offset: 0,
ChangeSize: 2,
Nums: repeatFloat64(-1.5, 130),
Name: "run switch to literal after h-byte overflow (negative version)",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -670,9 +672,9 @@ var (
1.6,
1.7,
},
Name: "increment literal",
Offset: 1,
ChangeSize: 2,
Name: "increment literal",
RewindOffset: 1,
ChangeSize: 2,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -690,9 +692,9 @@ var (
-1.6,
-1.7,
},
Name: "increment literal (negative version)",
Offset: 1,
ChangeSize: 2,
Name: "increment literal (negative version)",
RewindOffset: 1,
ChangeSize: 2,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -710,9 +712,9 @@ var (
1.4,
1.3,
},
Name: "increment literal (negative delta)",
Offset: 1,
ChangeSize: 2,
Name: "increment literal (negative delta)",
RewindOffset: 1,
ChangeSize: 2,
Buf: []byte{
0x9e, // base value
0x80, // delta 0
@@ -730,9 +732,9 @@ var (
-1.4,
-1.3,
},
Name: "increment literal (positive delta, negative version)",
Offset: 1,
ChangeSize: 2,
Name: "increment literal (positive delta, negative version)",
RewindOffset: 1,
ChangeSize: 2,
Buf: []byte{
0x9d, // base value
0x80, // delta 0
@@ -760,11 +762,11 @@ func TestInstantDeltaCompressor(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report = c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
if report.Offset != testCase.Offset {
t.Fatalf("%s: got offset %d are not equal expected %d",
testCase.Name, report.Offset, testCase.Offset)
if report.RewindOffset != testCase.RewindOffset {
t.Fatalf("%s: got rewindOffset %d are not equal expected %d",
testCase.Name, report.RewindOffset, testCase.RewindOffset)
}
if report.ChangeSize != testCase.ChangeSize {
t.Fatalf("%s: got changeSize %d are not equal expected %d",
@@ -798,7 +800,7 @@ func TestRestoreInstantDeltaCompressor(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report = c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
restored := NewValueDeltaCompressor(metricType, fracDigits, buf, c.Size())
if restored.baseValue != testCase.BaseValue {
@@ -825,7 +827,7 @@ func TestInstantDeltaDecompressorFromState(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report := c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
d := c.CreateDecompressor(metricType, fracDigits)
@@ -859,7 +861,7 @@ func TestInstantDeltaDecompressorFromEnd(t *testing.T) {
c := NewValueDeltaCompressor(metricType, fracDigits, buf, payloadSize)
for _, num := range testCase.Nums {
report := c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num, report.Delta)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num, report.Delta)
}
d := NewValueDeltaDecompressor(metricType, fracDigits)
@@ -890,16 +892,16 @@ var (
Buf []byte
LastUnixtime uint32
LastDelta uint32
Offset int
RewindOffset int
ChangeSize int
}{
{
Nums: []uint32{
1780777000,
},
Name: "add 1st value",
Offset: 0,
ChangeSize: 4,
Name: "add 1st value",
RewindOffset: 0,
ChangeSize: 4,
Buf: []byte{
0x00, 0x00, 0x00, 0x00,
0x28, 0x80, 0x24, 0x6a, // since
@@ -912,9 +914,9 @@ var (
1780777000,
1780777060, // +60
},
Name: "add 1st delta",
Offset: 0,
ChangeSize: 2,
Name: "add 1st delta",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x00, 0x00,
0x80, // h-byte (literal, len=1)
@@ -930,9 +932,9 @@ var (
1780777060, // +60
1780777120, // +60
},
Name: "literal changed to run",
Offset: 1,
ChangeSize: 1,
Name: "literal changed to run",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x00, 0x00,
0x00, // h-byte (run, len=2)
@@ -949,9 +951,9 @@ var (
1780777130, // +70
1780777200, // +70
},
Name: "literal decrease by 1 and switch to run",
Offset: 2,
ChangeSize: 3,
Name: "literal decrease by 1 and switch to run",
RewindOffset: 2,
ChangeSize: 3,
Buf: []byte{
0x00, // h-byte (run, len=2)
0xc6, // delta 70
@@ -969,9 +971,9 @@ var (
1780777120, // +60
1780777180, // +60
},
Name: "increment run",
Offset: 1,
ChangeSize: 1,
Name: "increment run",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x00, 0x00,
0x01, // h-byte (run, len=2)
@@ -989,9 +991,9 @@ var (
1780777180, // +60
1780777200, // +20
},
Name: "switch run to literal",
Offset: 0,
ChangeSize: 2,
Name: "switch run to literal",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x80, // h-byte (literal, len=1)
0x94, // delta 20
@@ -1003,10 +1005,10 @@ var (
LastDelta: 20,
},
{
Nums: generateProgression(1780777000, 60, 130),
Name: "increment run up to full filled h-byte",
Offset: 1,
ChangeSize: 1,
Nums: generateProgression(1780777000, 60, 130),
Name: "increment run up to full filled h-byte",
RewindOffset: 1,
ChangeSize: 1,
Buf: []byte{
0x00, 0x00,
0x7f, // h-byte (run, len=129)
@@ -1017,10 +1019,10 @@ var (
LastDelta: 60,
},
{
Nums: generateProgression(1780777000, 60, 131),
Name: "run switch to literal after h-byte overflow",
Offset: 0,
ChangeSize: 2,
Nums: generateProgression(1780777000, 60, 131),
Name: "run switch to literal after h-byte overflow",
RewindOffset: 0,
ChangeSize: 2,
Buf: []byte{
0x80, // h-byte (literal, len=1)
0xbc, // delta 60
@@ -1037,9 +1039,9 @@ var (
1780777060, // +60
1780777130, // +70
},
Name: "increment literal",
Offset: 1,
ChangeSize: 2,
Name: "increment literal",
RewindOffset: 1,
ChangeSize: 2,
Buf: []byte{
0x00,
0x81, // h-byte (literal, len=2)
@@ -1064,11 +1066,11 @@ func TestTimeDeltaCompressor(t *testing.T) {
c := NewTimeDeltaCompressor(buf, payloadSize)
for _, num := range testCase.Nums {
report = c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num)
}
if report.Offset != testCase.Offset {
t.Fatalf("%s: got offset %d are not equal expected %d",
testCase.Name, report.Offset, testCase.Offset)
if report.RewindOffset != testCase.RewindOffset {
t.Fatalf("%s: got rewindOffset %d are not equal expected %d",
testCase.Name, report.RewindOffset, testCase.RewindOffset)
}
if report.ChangeSize != testCase.ChangeSize {
t.Fatalf("%s: got changeSize %d are not equal expected %d",
@@ -1100,7 +1102,7 @@ func TestRestoreTimeDeltaCompressor(t *testing.T) {
c := NewTimeDeltaCompressor(buf, payloadSize)
for _, num := range testCase.Nums {
report = c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num)
}
restored := NewTimeDeltaCompressor(buf, c.Size())
if restored.lastUnixtime != testCase.LastUnixtime {
@@ -1118,16 +1120,17 @@ func TestTimeDeltaDecompressorFromState(t *testing.T) {
for _, testCase := range timeTestCases {
var (
tmp = make([]byte, tmpTimeSize)
buf = make([]byte, 8)
buf = make([]byte, 16)
payloadSize = 0
decodedNums []uint32
)
c := NewTimeDeltaCompressor(buf, payloadSize)
for _, num := range testCase.Nums {
report := c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num)
}
fmt.Println("-----")
d := c.CreateDecompressor()
for {
num, done := d.NextValue()
@@ -1157,7 +1160,7 @@ func TestTimeDeltaDecompressorFromEnd(t *testing.T) {
c := NewTimeDeltaCompressor(buf, payloadSize)
for _, num := range testCase.Nums {
report := c.Evaluate(tmp, num)
c.Append(report.Offset, tmp[:report.ChangeSize], num)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num)
}
c.ReplaceSinceWithUntil()
@@ -1206,3 +1209,91 @@ func generateProgression(start uint32, delta uint32, n int) []uint32 {
}
return nums
}
func generateTimestamps(days int) (timestamps []uint32) {
var (
minutes = []int{14, 29, 44, 59}
hoursPerDay = 24
totalHours = days * hoursPerDay
since = time.Now().AddDate(0, 0, -days)
)
for i := range totalHours {
hourTime := since.Add(time.Duration(i) * time.Hour)
for _, m := range minutes {
measureTime := time.Date(
hourTime.Year(),
hourTime.Month(),
hourTime.Day(),
hourTime.Hour(),
m, // minutes
0, // seconds
0, // nanoseconds
time.Local,
)
timestamps = append(timestamps, uint32(measureTime.Unix()))
}
}
return
}
func TestXXX(t *testing.T) {
var (
timestamps = generateTimestamps(20)[:1231]
tmp = make([]byte, tmpTimeSize)
buf = make([]byte, 64)
payloadSize = 0
decodedNums []uint32
)
c := NewTimeDeltaCompressor(buf, payloadSize)
for _, num := range timestamps {
report := c.Evaluate(tmp, num)
c.Append(report.RewindOffset, tmp[:report.ChangeSize], num)
}
d := c.CreateDecompressor()
for {
num, done := d.NextValue()
if done {
break
}
decodedNums = append(decodedNums, num)
}
slices.Reverse(decodedNums)
if !slices.Equal(timestamps, decodedNums) {
t.Fatalf("got nums %v not equal expected %v",
decodedNums, timestamps)
}
}
func TestYYY(t *testing.T) {
buf, err := textutil.ParseHex("50 04 87 ac 6b 05 6a")
if err != nil {
t.Fatal(err)
}
//var decodedNums []uint32
var prev uint32
d := NewTimeDeltaDecompressor()
d.RestoreFromEnd(buf)
for {
num, done := d.NextValue()
if done {
break
}
fmt.Println(num, prev-num)
prev = num
//decodedNums = append(decodedNums, num)
}
// //slices.Reverse(decodedNums)
// for _, num := range decodedNums {
// }
}