multiplication-table/main.go

145 lines
2.7 KiB
Go

package main
import (
"encoding/csv"
"fmt"
"github.com/lucasb-eyer/go-colorful"
"image"
"image/draw"
"image/png"
"log"
"os"
"strconv"
)
const OutputEnable = true
const CreateImage = true
const LightColor = `#00fbfb`
const DarkColor = `#330066`
func main() {
number, err := strconv.Atoi(os.Args[1])
if err != nil {
log.Fatal("Please enter a valid number.")
}
matrice := make([][]int, number+1)
var inverses []int
for i := 0; i <= number; i++ {
matrice[i] = make([]int, number+1)
for j := 0; j <= number; j++ {
multiple := (j * i) % number
matrice[i][j] = multiple
if multiple == 1 {
inverses = append(inverses, j)
}
}
}
// Save it
if err := csvExport(matrice); err != nil {
log.Fatal(err)
}
// output it
if OutputEnable {
fmt.Print("\t")
for i := 0; i <= number; i++ {
fmt.Print(i, "\t")
}
fmt.Println()
for rownumber, row := range matrice {
fmt.Print(rownumber, "\t")
for _, col := range row {
fmt.Print(col, "\t")
}
fmt.Println()
}
fmt.Println("Inverses: ", inverses)
}
// Build an image
if CreateImage {
log.Println("Starting image creation...")
size := getImageBlockSize(number)
lightColor, _ := colorful.Hex(LightColor)
darkColor, _ := colorful.Hex(DarkColor)
img := image.NewRGBA(image.Rect(0, 0, number*size+size-1, number*size+size-1))
for rownumber, row := range matrice {
for colnumber, col := range row {
x := colnumber*size - 1
y := rownumber*size - 1
draw.Draw(img, image.Rect(x, y, x+size, y+size), &image.Uniform{lightColor.BlendRgb(darkColor, float64(col)/float64(number-1))}, image.ZP, draw.Src)
}
}
imgpath := strconv.Itoa(number) + "x.png"
toimg, err := os.Create(imgpath)
if err != nil {
log.Fatal(err)
}
defer toimg.Close()
err = png.Encode(toimg, img)
if err != nil {
log.Fatal(err)
}
log.Println("Image saved to " + imgpath)
}
}
func csvExport(data [][]int) error {
file, err := os.Create("result.csv")
if err != nil {
return err
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
//Prepare
dataStrings := make([][]string, len(data))
for in := range data {
dataStrings[in] = make([]string, len(data[in]))
for in2, val2 := range data[in] {
dataStrings[in][in2] = strconv.Itoa(val2)
}
}
for _, value := range dataStrings {
if err := writer.Write(value); err != nil {
return err // let's return errors if necessary, rather than having a one-size-fits-all error handler
}
}
return nil
}
func getImageBlockSize(number int) int {
if number < 50 {
return 10
}
if number < 100 {
return 8
}
if number < 200 {
return 4
}
if number < 500 {
return 3
}
if number < 900 {
return 2
}
return 1
}