Here is currently my Python code for today. Took me some time because I did not understand that we had to sum the indeces of the pots(!).
For part 2 I am looking for loops in the evolution, so that if we reach a plant state (regardless of the indeces) that we have reached before, we loop over those same circular steps without recalculation until reaching to the end.
I could clean up a little, especially the code that cleans up the borders. Maybe if I find time I will do it, but I first hope to later make a Golang solution based on my Python code.
importrewithopen('input')asf:data=f.readlines()# Read plants and add padding of statically empty pots left and right
# Since the rules only take two pots to left and right into account,
# we are guaranteed that adding four pots left and right is sufficient.
plants_initial="...."+data[0][15:-1]+"...."# Read and save rules
rules={}foriinrange(2,len(data)):rule_match=re.match(r'([#|\.]+) => ([#|\.])',data[i])rule,res=rule_match.group(1),rule_match.group(2)rules[rule]=res# Evolve generations
defevolve(generations):plants=list(plants_initial)# Clean start with initial plants
seen={}# Keep track of loops when evolving
shift=-4# Added padding must be accounted for by shifting
e=0# Initial evolve step
whilee<generations:e+=1# Evolve step
plants_copy=plants.copy()foridx,plantinenumerate(plants):# Ignore outer borders which extend infinitely with empty pots (".")
ifidx<2oridx>len(plants)-3:continue# For real inputs all rules are defined. But for example we would
# have to use (".") if rule was not defined for this pot.
plants_copy[idx]=rules.get(''.join(plants[idx-2:idx+3]),".")ifplants_copy[3]=='#':# If we planted close to the left border, we must extend it:
plants_copy.insert(0,'.')shift-=1# Adjusts the pot index shifting
elifplants_copy[:5]==['.']*5:# If we have deserted the whole left border, we can remove one pot:
plants_copy.remove('.')shift+=1# Adjusts the pot index shifting
ifplants_copy[-3]=='#':# If we planted close to the right border, we must extend it:
plants_copy.append('.')elifplants_copy[-4:]==['.']*5:# If we have deserted the whole right border, we can remove one pot:
plants_copy=plants_copy[:-1]plants=plants_copyifseen.get(''.join(plants),False):# We have made a full circle! No need to recalculate next steps.
# We can just warp into the future...
circle_length=e-seen[''.join(plants)][0]# The steps of this circle
circles=(generations-e)//circle_length# The circles to make
e+=circles*circle_length# Warping into future...
shift_length=shift-seen[''.join(plants)][1]# The shifts this circle performs
shift+=circles*shift_length# Adjusting shifts
seen[''.join(plants)]=(e,shift)# Add unseen pattern to dictionary
returnplants,shift# Part 1:
plants,shift=evolve(generations=20)print('Part 1:')print(sum(i+shiftfori,pinenumerate(plants)ifp=='#'))# Part 2:
plants,shift=evolve(generations=50000000000)print('Part 2:')print(sum(i+shiftfori,pinenumerate(plants)ifp=='#'))
Here is the Golang code. I don't think this is the best way of doing it in Golang, but it does the job!
packagemainimport("bufio""fmt""os""reflect""regexp")typeentrystruct{eintshiftint}// readLines reads a whole file into memory// and returns a slice of its lines.funcreadLines(pathstring)([]string,error){file,err:=os.Open(path)iferr!=nil{returnnil,err}deferfile.Close()varlines[]stringscanner:=bufio.NewScanner(file)forscanner.Scan(){lines=append(lines,scanner.Text())}returnlines,scanner.Err()}// function to evolve generations.funcevolve(generationsint)([]rune,int){seen:=make(map[string]entry)shift:=-4plantsCopy:=make([]rune,len(plants))plantsOld:=make([]rune,len(plants))copy(plantsOld,plants)fore:=1;e<=generations;e++{plantsCopy=make([]rune,len(plantsOld))copy(plantsCopy,plantsOld)foridx:=rangeplantsOld{ifidx<2||idx>len(plantsOld)-3{continue}plantsCopy[idx]=rules[string(plantsOld[idx-2:idx+3])]}ifplantsCopy[3]=='#'{plantsCopy=append(plantsCopy,0)copy(plantsCopy[1:],plantsCopy[0:])plantsCopy[0]='.'shift--}elseifreflect.DeepEqual(plantsCopy[:5],[]rune{'.','.','.','.','.'}){plantsCopy=plantsCopy[1:]shift++}ifplantsCopy[len(plantsCopy)-3]=='#'{plantsCopy=append(plantsCopy,'.')}elseifreflect.DeepEqual(plantsCopy[len(plantsCopy)-5:],[]rune{'.','.','.','.','.'}){plantsCopy=plantsCopy[:len(plantsCopy)-1]}ifval,ok:=seen[string(plantsCopy)];ok{circleLength:=e-val.ecircles:=(generations-e)/circleLengthe=e+circles*circleLengthshiftLength:=shift-val.shiftshift=shift+circles*shiftLength}seen[string(plantsCopy)]=entry{e:e,shift:shift}plantsOld=make([]rune,len(plantsCopy))copy(plantsOld,plantsCopy)}returnplantsCopy,shift}varplants[]runevarrulesmap[string]runefuncmain(){data,err:=readLines("input")iferr!=nil{panic(err)}plantsInitial:="...."+data[0][15:]+"...."plants=[]rune(plantsInitial)rules=make(map[string]rune)r,_:=regexp.Compile("([#|\\.]+) => ([#|\\.])")for_,d:=rangedata[2:]{rule:=r.FindStringSubmatch(d)[1]res:=r.FindStringSubmatch(d)[2]rules[rule]=[]rune(res)[0]}// Part 1:plants,shift:=evolve(20)fmt.Println("Part 1:")varsumintsum=0fori,p:=rangeplants{ifp=='#'{sum+=i+shift}}fmt.Println(sum)// Part 2:plants,shift=evolve(50000000000)fmt.Println("Part 2:")sum=0fori,p:=rangeplants{ifp=='#'{sum+=i+shift}}fmt.Println(sum)}
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Here is currently my Python code for today. Took me some time because I did not understand that we had to sum the indeces of the pots(!).
For part 2 I am looking for loops in the evolution, so that if we reach a plant state (regardless of the indeces) that we have reached before, we loop over those same circular steps without recalculation until reaching to the end.
I could clean up a little, especially the code that cleans up the borders. Maybe if I find time I will do it, but I first hope to later make a Golang solution based on my Python code.
Here is the Golang code. I don't think this is the best way of doing it in Golang, but it does the job!