package main import ( "os" "fmt" "strconv" "strings" ) // general util func check(e error) { if e != nil { panic(e) } } func file_index(mem []int, id int) []int { offset := -1 for i, elem := range mem { if elem == id { offset = i break } } if offset == -1 { return nil } length := 1 for i := offset + 1; i < len(mem); i++ { if mem[i] == id { length++ } else { break } } return []int{offset, offset + length} } func cp(mem []int, id int) bool { file_idx := file_index(mem, id) file_len := file_idx[1] - file_idx[0] target_mem := mem[:file_idx[0]] i := 0 for { if i > len(target_mem) { break } space_idx := file_index(target_mem[i:], -1) if space_idx == nil { break } space_len := space_idx[1] - space_idx[0] if space_len >= file_len { // copy copy(mem[i + space_idx[0]: i + space_idx[1]], mem[file_idx[0]:file_idx[1]]) return true } i += space_idx[1] + 1 } return false } // main loop func main() { // read in file dat, err := os.ReadFile("data.txt") check(err) dat_str := strings.TrimSpace(string(dat)) // contruct input as int arr input := make([]int, 0, len(dat_str)) mem_size := 0 for _, char := range []rune(dat_str) { num, err := strconv.Atoi(string(char)) check(err) mem_size += num input = append(input, num) } // convert to actual memory representation mem := make([]int, 0, mem_size) is_file := true file_id := 0 for _, elem := range input { if is_file { for range elem { mem = append(mem, file_id) } file_id++ } else { for range elem { mem = append(mem, -1) } } is_file = !is_file } // reorder for i := file_id - 1; i > 0; i-- { file_idx := file_index(mem, i) if cp(mem, i) { // clear old file for i := file_idx[0]; i < file_idx[1]; i++ { mem[i] = -1 } } } // calc checksum checksum := 0 for i, elem := range mem { if elem == -1 { continue } checksum += i * elem } fmt.Println(checksum) }