-
Notifications
You must be signed in to change notification settings - Fork 0
/
csv_loader.go
109 lines (94 loc) · 2.77 KB
/
csv_loader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package main
import (
"bytes"
"encoding/csv"
"fmt"
"github.com/rs/zerolog/log"
"os"
"strconv"
)
// Read the input CSV file specified by its path and load a board from its content.
func readInputFile(filePath string, checkSquare bool) (*Board, error) {
// Load the raw string file content.
f, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("unable to open the input file: %w", err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
log.Fatal().Err(err).Msg("unable to close the input file")
}
}(f)
records, err := csv.NewReader(f).ReadAll()
if err != nil {
return nil, fmt.Errorf("unable to parse the input CSV file: %w", err)
}
// Parse it.
cells := make(map[int]int)
for iRow, columns := range records {
for iCol, colorStr := range columns {
cellId := (iRow * len(columns)) + iCol
color, err := strconv.Atoi(colorStr)
if err != nil {
return nil, fmt.Errorf("invalid color for row=%d, col=%d, color=%s : %w", iRow+1, iCol+1, colorStr, err)
}
cells[cellId] = color
}
}
// Check that the board is a square.
nbRows := len(records)
nbCols := len(cells) / nbRows
if checkSquare && len(cells) != (nbRows*nbRows) {
return nil, fmt.Errorf("invalid row and column count, the board must be a square")
}
return NewBoard(nbRows, nbCols, cells), nil
}
// Serialize a board to it's CSV string representation.
func serializeBoardToCsv(board *Board) (string, error) {
// Create a CSV writer on top of a byte buffer.
buffer := new(bytes.Buffer)
csvWriter := csv.NewWriter(buffer)
// Add a record to the writer for each row in the board.
for iRow := 0; iRow < board.nbRows; iRow++ {
// Create the row record.
record := make([]string, board.nbCols)
for iCol := 0; iCol < board.nbCols; iCol++ {
cellId := (iRow * board.nbCols) + iCol
color := board.cells[cellId]
record[iCol] = strconv.Itoa(color)
}
// Add it to the writer.
err := csvWriter.Write(record)
if err != nil {
return "", fmt.Errorf("unable to serialize the record as CSV: %w", err)
}
}
// Flush the writer and return the resulting CSV string.
csvWriter.Flush()
csvStr := buffer.String()
return csvStr, nil
}
func writeOutputFile(fileName string, steps []int) error {
// Open the file for writing.
f, err := os.Create(fileName)
if err != nil {
return fmt.Errorf("unable to open the output file: %w", err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
log.Fatal().Err(err).Msg("unable to close the output file")
}
}(f)
// Create the CSV writer and append all the steps.
writer := csv.NewWriter(f)
defer writer.Flush()
for _, color := range steps {
record := []string{strconv.Itoa(color)}
if err := writer.Write(record); err != nil {
return fmt.Errorf("error writing record to file: %w", err)
}
}
return nil
}