145 lines
2.7 KiB
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
|
|
}
|