package main

import (
	"bufio"
	"fmt"
	"log"
	"math"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)
const FieldsCount = 149
// AField returns zero-based index for field A<n>
func AField(n int) int { return n - 1 }
// Helper: floating-point equality tolerance
func floatEquals(a, b float64) bool {
	const epsilon = 0.0001
	return math.Abs(a-b) < epsilon
}
// Parses one line from [ca/:A1,A2,...] into a float64 slice
func parseLine(line string) ([]float64, error) {
	line = strings.TrimSpace(line)
	if !strings.HasPrefix(line, "[ca/:") || !strings.HasSuffix(line, "]") {
	return nil, fmt.Errorf("Invalid line format")
	}
	content := line[5 : len(line)-1]
	parts := strings.Split(content, ",")
	if len(parts) < FieldsCount {
		return nil, fmt.Errorf("Not enough fields: %d", len(parts))
	}
	fields := make([]float64, FieldsCount)
	for i, p := range parts[:FieldsCount] {
		v, err := strconv.ParseFloat(p, 64)
		if err != nil {
			return nil, fmt.Errorf("Parse float error at field %d: %v", i+1, err)
		}
		fields[i] = v
	}
	return fields, nil
}
// Formats fields slice back to line string
func formatLine(fields []float64) string {
	parts := make([]string, len(fields))
	for i, v := range fields {
		if floatEquals(v, float64(int64(v))) {
			parts[i] = strconv.FormatInt(int64(v), 10)
		} else {
			parts[i] = fmt.Sprintf("%.5g", v)
		}
	}
	return "[ca/:" + strings.Join(parts, ",") + "]"
}
// Reads file, returns slice of line offsets and (A2,A3) values and maxID
// It store offsets so it can seek and read lines on demand, not full contents
func scanFileForParents(path string) (parent1Offsets []int64, parent2Offsets []int64, maxID int64, err error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, nil, 0, err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	offset := int64(0)
	for scanner.Scan() {
		line := scanner.Text()
		fields, err := parseLine(line)
		if err != nil {
			return nil, nil, 0, err
		}
		id := int64(fields[AField(1)])
		if id > maxID {
			maxID = id
		}
		a2 := fields[AField(2)]
		a3 := fields[AField(3)]
		if floatEquals(a2, 1) && floatEquals(a3, 1) {
			parent1Offsets = append(parent1Offsets, offset)
		} else {
			parent2Offsets = append(parent2Offsets, offset)
		}
		// +1 for newline
		offset += int64(len(line)) + 1
	}
	if err := scanner.Err(); err != nil {
		return nil, nil, 0, err
	}
	return parent1Offsets, parent2Offsets, maxID, nil
}
// Reads one line at offset (assumes lines end with \n)
func readLineAtOffset(f *os.File, offset int64) ([]float64, error) {
	_, err := f.Seek(offset, 0)
	if err != nil {
		return nil, err
	}
	reader := bufio.NewReader(f)
	line, err := reader.ReadString('\n')
	if err != nil {
		return nil, err
	}
	fmt.Printf("Read line: '%s'\n", line)
	return parseLine(strings.TrimSpace(line))
}
// Helper for random choose 1 element from slices of float64
func choice(s []float64) float64 {
	return s[rand.Intn(len(s))]
}
// Helper clamp to 0-255 ints
func clampInt(i int) int {
	if i < 0 {
		return 0
	} else if i > 255 {
		return 255
	}
	return i
}
// Copy or set fields conditionally helper
// If condition==true, set all fields [from:to] to trueVal
// Else if trueVal==falseVal==0, randomly copy from p1 or p2 for all these fields
// Else set all fields [from:to] to falseVal
func copyOrSetConditional(offspring, p1, p2 []float64, from, to int, condition bool, trueVal, falseVal float64) {
	if condition {
		for i := from; i <= to; i++ {
			offspring[i] = trueVal
		}
	} else if trueVal == 0 && falseVal == 0 {
		if rand.Intn(2) == 0 {
			copy(offspring[from:to+1], p1[from:to+1])
		} else {
			copy(offspring[from:to+1], p2[from:to+1])
		}
	} else {
		for i := from; i <= to; i++ {
			offspring[i] = falseVal
		}
	}
}
// Create offspring fields per rules, given parents p1 and p2 fields, new ID
func createOffspring(p1, p2 []float64, newID int64) []float64 {
	offspring := make([]float64, FieldsCount)
	offspring[AField(1)] = float64(newID)
	// Rule 2
	a2Candidates := []float64{p1[AField(2)], p1[AField(3)], p2[AField(2)], p2[AField(3)]}
	a2 := choice(a2Candidates)
	offspring[AField(2)] = a2
	if a2 == p1[AField(2)] || a2 == p1[AField(3)] {
		offspring[AField(3)] = choice([]float64{p2[AField(2)], p2[AField(3)]})
	} else {
		offspring[AField(3)] = choice([]float64{p1[AField(2)], p1[AField(3)]})
	}
	// Rule 3
	a4Candidates := []float64{p1[AField(4)], p1[AField(5)], p2[AField(4)], p2[AField(5)]}
	a4 := choice(a4Candidates)
	offspring[AField(4)] = a4
	if a4 == p1[AField(4)] || a4 == p1[AField(5)] {
		offspring[AField(5)] = choice([]float64{p2[AField(4)], p2[AField(5)]})
	} else {
		offspring[AField(5)] = choice([]float64{p1[AField(4)], p1[AField(5)]})
	}
	// Rule 4: A6...A9 from p1 or p2 + random offset
	source := p1
	if rand.Intn(2) == 1 {
		source = p2
	}
	for i := AField(6); i <= AField(9); i++ {
		base := int(source[i])
		offset := rand.Intn(21) - 10
		offspring[i] = float64(clampInt(base + offset))
	}
	// Rule 5: A10...A12 pick all from p1 or p2 randomly
	if rand.Intn(2) == 0 {
		copy(offspring[AField(10):AField(13)], p1[AField(10):AField(13)])
	} else {
		copy(offspring[AField(10):AField(13)], p2[AField(10):AField(13)])
	}
	// Rule 6 A13
	fmt.Printf("Debug A2=%.6f, A3=%.6f\n", offspring[AField(2)], offspring[AField(3)])
	a2a311 := floatEquals(offspring[AField(2)], 1) && floatEquals(offspring[AField(3)], 1)
	a2a322 := floatEquals(offspring[AField(2)], 2) && floatEquals(offspring[AField(3)], 2)
	fmt.Printf("Condition a2a311=%v, a2a322=%v\n", a2a311, a2a322)
	if a2a311 || a2a322 {
		// 0.25 to 0.5
		rv := float64(rand.Intn(26)+25) / 100
		fmt.Printf("Setting A13 to %.3f\n", rv)
		offspring[AField(13)] = rv
	} else {
		fmt.Println("Setting A13 to 1")
		offspring[AField(13)] = 1
	}
	// Rule 7: A14...A16 pick from one parent randomly
	if rand.Intn(2) == 0 {
		copy(offspring[AField(14):AField(17)], p1[AField(14):AField(17)])
	} else {
		copy(offspring[AField(14):AField(17)], p2[AField(14):AField(17)])
	}
	// Rule 8: A17 same pattern as A13
	if a2a311 || a2a322 {
		offspring[AField(17)] = float64(rand.Intn(26)+25) / 100
	} else {
		offspring[AField(17)] = 1
	}
	// Rule 9: A18...A20 pick from one parent randomly
	if rand.Intn(2) == 0 {
		copy(offspring[AField(18):AField(21)], p1[AField(18):AField(21)])
	} else {
		copy(offspring[AField(18):AField(21)], p2[AField(18):AField(21)])
	}
	// Rule 10: A21 conditional
	if a2a311 {
		offspring[AField(21)] = float64(rand.Intn(26)+25) / 100
	} else {
		offspring[AField(21)] = 0
	}
	// Rules 11-16 combined using helper:
	type condRule struct {
		from, to       int
		condition      bool
		trueVal, falseVal float64
	}
	rules := []condRule{
		// Rule 11: A22-A24 choose parent
		{AField(22), AField(24), false, 0, 0},
		// Rule 12: A25 conditional value
		{AField(25), AField(25), a2a311 || a2a322, 0, 1},
		// Rule 13: A26-A28 choose parent
		{AField(26), AField(28), false, 0, 0},
		// Rule 14: A29 conditional value
		{AField(29), AField(29), a2a311 || a2a322, 0, 1},
		// Rule 15: A30-A32 choose parent
		{AField(30), AField(32), false, 0, 0},
		// Rule 16: A33 conditional value
		{AField(33), AField(33), a2a311, 0, 1},
	}
	for _, r := range rules {
		copyOrSetConditional(offspring, p1, p2, r.from, r.to, r.condition, r.trueVal, r.falseVal)
	}
	// Rule 17: A34-A39 pick parent independently, then randomly mutate 1-3 times
	for i := AField(34); i <= AField(39); i++ {
		if rand.Intn(2) == 0 {
			offspring[i] = p1[i]
		} else {
			offspring[i] = p2[i]
		}
	}
	toChangeCount := rand.Intn(3) + 1
	indices := rand.Perm(6)[:toChangeCount]
	for _, idx := range indices {
		pos := AField(34) + idx
		old := offspring[pos]
		newVal := float64(rand.Intn(10) + 1)
		for floatEquals(newVal, old) {
			newVal = float64(rand.Intn(10) + 1)
		}
		offspring[pos] = newVal
	}
	// Rule 18-19: A40, A41 random 1-10
	offspring[AField(40)] = float64(rand.Intn(10) + 1)
	offspring[AField(41)] = float64(rand.Intn(10) + 1)
	// Rule 20: A42 complex mapping
	a2v := int(offspring[AField(2)])
	a3v := int(offspring[AField(3)])
	a4v := int(offspring[AField(4)])
	var a42 float64
	switch {
	case a2v == 1 && a3v == 1 && a4v == 1:
		a42 = 1
	case a2v == 1 && a3v == 1 && a4v == 2:
		a42 = 2
	case a2v == 1 && a3v == 1 && a4v == 3:
		a42 = 3
	case a2v == 2 && a3v == 2 && a4v == 1:
		a42 = 4
	case a2v == 2 && a3v == 2 && a4v == 2:
		a42 = 5
	case a2v == 2 && a3v == 2 && a4v == 3:
		a42 = 6
	case (a2v == 1 && a3v == 2 && a4v == 1) || (a2v == 2 && a3v == 1 && a4v == 1):
		a42 = 7
	case (a2v == 1 && a3v == 2 && a4v == 2) || (a2v == 2 && a3v == 1 && a4v == 2):
		a42 = 8
	case (a2v == 1 && a3v == 2 && a4v == 3) || (a2v == 2 && a3v == 1 && a4v == 3):
		a42 = 9
	default:
		a42 = 0
	}
	offspring[AField(42)] = a42
	// Rule 21-22: A43, A44
	A147 := p1[AField(147)]
	if a2a311 {
		offspring[AField(43)] = A147
		offspring[AField(44)] = A147
	} else {
		offspring[AField(43)] = 404
		offspring[AField(44)] = 404
	}
	// Rule 23: A45
	if a2a311 || a2a322 {
		offspring[AField(45)] = 404
	} else {
		offspring[AField(45)] = A147
	}
	// Rule 24: A46
	if a2a311 {
		offspring[AField(46)] = 404
	} else {
		offspring[AField(46)] = A147
	}
	// Rule 25: Sum A47...A146 = p1 + p2
	for i := AField(47); i <= AField(146); i++ {
		offspring[i] = p1[i] + p2[i]
	}
	// Rule 26: Find max in A47...A146, set A147 = max index-46
	maxIdx := AField(47)
	maxVal := offspring[AField(47)]
	for i := AField(48); i <= AField(146); i++ {
		if offspring[i] > maxVal {
			maxVal = offspring[i]
			maxIdx = i
		}
	}
	offspring[AField(147)] = float64(maxIdx - AField(46))
	// Rule 27: Set offspring's A148 = p1's A1, A149 = p2's A1 (parents' IDs)
	offspring[AField(148)] = p1[AField(1)]
	offspring[AField(149)] = p2[AField(1)]
	return offspring
}
func main() {
	rand.Seed(time.Now().UnixNano())
	file := "CA.txt"
	// Step 1: Scan file offsets of parents (store minimal info to be memory-friendly)
	parent1Offsets, parent2Offsets, maxID, err := scanFileForParents(file)
	if err != nil {
		log.Fatalf("Failed scanning file: %v", err)
	}
	if len(parent1Offsets) == 0 || len(parent2Offsets) == 0 {
		log.Fatal("No suitable parents found")
	}
	// Pick random offsets:
	offset1 := parent1Offsets[rand.Intn(len(parent1Offsets))]
	offset2 := parent2Offsets[rand.Intn(len(parent2Offsets))]
	// Open file for reading parents
	f, err := os.Open(file)
	if err != nil {
		log.Fatalf("Failed to open file: %v", err)
	}
	defer f.Close()
	p1, err := readLineAtOffset(f, offset1)
	if err != nil {
		log.Fatalf("Failed to read parent1 at offset %d: %v", offset1, err)
	}
	p2, err := readLineAtOffset(f, offset2)
	if err != nil {
		log.Fatalf("Failed to read parent2 at offset %d: %v", offset2, err)
	}
	offspring := createOffspring(p1, p2, maxID+1)
	// Append offspring to file
	outf, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Failed opening file to append: %v", err)
	}
	defer outf.Close()
	line := formatLine(offspring)
	_, err = outf.WriteString(line + "\n")
	if err != nil {
		log.Fatalf("Failed to write offspring: %v", err)
	}
	fmt.Println("Offspring created and appended:")
	fmt.Println(line)
}
 Failed scanning file: Parse float error at field 149: strconv.ParseFloat: parsing "1][ca/:21": invalid syntax
exit status 1
What's wrong?