5 filename=${1:-example.txt}
16 # data per line is like this:
17 # <x=val, y=val, z=val>
36 while read -u 3 line; do
38 vals=( $(parse_line "$line") )
40 for pair in "${vals[@]}"; do
43 moons["${moon_number}_${key}"]=$val
44 # also set the velocity of each to 0
45 moons["${moon_number}_${key}v"]=0
60 for (( a=1; a<=$moon_count; a++ )); do
61 for (( b=1; b<=$moon_count; b++ )); do
62 if [ $a -eq $b ]; then
65 # to make our brain not hurt we only do
66 # the calculation for the velocity on $a
67 # it's not as efficient as doing both $a
68 # and $b, but that also then needs a way
69 # to skip already done pair calcs
71 val1=${moons[${a}_${key}]}
72 val2=${moons[${b}_${key}]}
73 if [ $val1 -gt $val2 ]; then
74 moons[${a}_${key}v]=$((${moons[${a}_${key}v]}-1))
75 elif [ $val1 -lt $val2 ]; then
76 moons[${a}_${key}v]=$((${moons[${a}_${key}v]}+1))
87 for (( a=1; a<=$moon_count; a++ )); do
89 let moons[${a}_${key}]+=${moons[${a}_${key}v]}
94 display_moons_gravity_and_velocity() {
95 for (( a=1; a<=$moon_count; a++ )); do
96 echo -n "pos=<x=${moons[${a}_x]}, y=${moons[${a}_y]}, z=${moons[${a}_z]}>, "
97 echo "vel=<x=${moons[${a}_xv]}, y=${moons[${a}_yv]}, z=${moons[${a}_zv]}>"
109 temp="${moons[${moon}_x${suffix}]} ${moons[${moon}_y${suffix}]} ${moons[${moon}_z${suffix}]}"
112 for val in "${vals[@]}"; do
119 get_potential_energy() {
123 get_kinetic_energy() {
129 local -i got_states=0
130 add_state $step x || got_states+=1
131 add_state $step y || got_states+=1
132 add_state $step z || got_states+=1
134 if [ $got_states -eq 3 ]; then
144 if [ ${cycles[$key]+a} ]; then
148 state="$(get_state_string $key)$(get_state_string ${key}v)"
150 if [ ${states[${key}_${state}]+a} ]; then
151 if [ ${states[${key}_${state}]} -eq 0 ]; then
156 states["${key}_${state}"]=$step
164 for (( moon=1; moon<=$moon_count; moon++ )); do
165 state+="${moons[${moon}_${key}]}|"
172 local -a values=( $@ )
173 local -A factor_counts
180 for value in ${values[@]}; do
182 factors=( $(get_prime_factors $value) )
183 local -A temp_factor_counts
184 for factor in ${factors[@]}; do
185 if [ ${temp_factor_counts[$factor]+a} ]; then
186 temp_factor_counts[$factor]=$((${temp_factor_counts[$factor]}+1))
188 temp_factor_counts[$factor]=1
191 # loop through temp_factor_counts before we clear it
192 for factor in ${!temp_factor_counts[@]}; do
193 if [ ${factor_counts[$factor]+a} ]; then
194 if [ ${temp_factor_counts[$factor]} -gt ${factor_counts[$factor]} ]; then
195 factor_counts[$factor]=${temp_factor_counts[$factor]}
198 factor_counts[$factor]=${temp_factor_counts[$factor]}
201 unset temp_factor_counts
205 for factor in "${!factor_counts[@]}"; do
206 power=${factor_counts[$factor]}
207 value=$(($factor**$power))
214 get_prime_factors() {
218 # start with the biggest prime, work down until we hit a prime
219 for (( a=$((${#primes[@]}-1)); a>=0; a-- )); do
221 while [ $(( val % $prime )) -eq 0 ]; do
225 if [ $val -eq 1 ]; then
233 calculate_primes_required() {
235 local highest=${vals[0]}
236 declare -g -a primes=( 2 )
239 for val in ${vals[@]}; do
240 if [ $val -gt $highest ]; then
245 for (( a=3; a<=$highest; a++ )); do
246 for prime in ${primes[@]}; do
247 if [ $((a%prime)) -eq 0 ]; then
258 display_moons_gravity_and_velocity
261 for (( step=1; step<=$steps; step++ )); do
265 if [ $((step % $display_steps)) -eq 0 ]; then
267 display_moons_gravity_and_velocity
272 # get the kinetic and potential energy for each moon
273 # and the whole system
275 for (( moon=1; moon<=$moon_count; moon++ )); do
276 pe=$(get_potential_energy $moon)
277 ke=$(get_kinetic_energy $moon)
279 let total_energy+=$te
280 echo "Moon $moon: PE=$pe, KE=$ke, TE=$te"
283 echo "System total energy: $total_energy"
285 echo "Looking for duplicate state, this could take a while"
286 spinner_parts=( '-' '/' '|' '\' )
288 printf '\r%s' ${spinner_parts[$(($step%4))]}
292 while [ $keep_going -eq 1 ]; do
293 printf '\r%s' ${spinner_parts[$(($step%4))]}
296 if ! add_states $step; then
303 for key in ${!cycles[@]}; do
304 echo "${key} cycles every ${cycles[$key]} steps"
306 echo "Calculating primes..."
307 calculate_primes_required "${cycles[@]}"
308 echo "Calculating repeat cycle..."
309 repeat_cycle="$(get_lcm ${cycles[@]})"
310 echo "Steps to get to a repeat: $repeat_cycle"