Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Solving a (simple) numeric exercise in bash

Tags:

bash

math

Some of you are probably familiar with Project Euler, and I'm currently attempting a few of their problems to teach myself some more bash. They're a bit more mathematical than 'script-y' but it helps with syntax etc.

The problem currently asks me to solve:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

The code I have looks like so:

#!/bin/bash

i="1"

for i in `seq 1 333`
do
    threes[$i]=`calc $i*3` # where 'calc' is a function written in bashrc
    #calc actually looks like: calc() {awk "BEGIN { print "$*"} }

    let "sumthrees = sumthrees + ${threes[$i]}"
done

for i in `seq 1 199`
do
    fives[$i]=`calc $i*5`
    let "sumfives = sumfives + ${fives[$i]}"
done

let "ans = $sumfives + $sumthrees"

echo "The sum of all 3 factors is $sumthrees and the sum of all five factors is $sumfives"
echo "The sum of both is $ans"

#So I can repeatedly run the script without bash remembering the variables between executions
unset i
unset fives
unset threes
unset sumfives
unset sumthrees
unset ans

So far I've not gotten the correct answer, but have run out of ideas as to where I'm going wrong. (FYI, the script currently gives me 266333, which I believe is close, but I don't know the answer yet.)

Can anyone spot anything? And for my own learning, if there are more elegant solutions to this that people might like to share that would be great.

EDIT

Thanks for all the answers, super informative. Since there are so many useful answers here I'll accept my favourite as the proper thread answer.

like image 946
Joe Healey Avatar asked Jul 12 '26 17:07

Joe Healey


2 Answers

  • Blue Moon pointed out the actual problem with your logic.

  • You don't need to store all the threes and fives in arrays because you don't need them later.

  • You don't need to unset variables at the end of a script if you use ./yourscript or bash script because they'll disappear along with the shell instance (better to initialize them first in any case).

  • You don't need awk to do math, bash does that just fine.

  • seq and let are not the best way to do anything in a bash script.

Here's a straight forward version:

#!/bin/bash
sum=0
for ((i=1; i<1000; i++))
do
  if (( i%3 == 0 || i%5 == 0 ))
  then
    (( sum += i ))
  fi
done
echo "$sum"
like image 57
that other guy Avatar answered Jul 14 '26 11:07

that other guy


Your logic is almost right except that there are numbers which divide by both 3 and 5. So you are adding these numbers twice. Hence, you get wrong answer.

Use another loop similar to ones you have and subtract the ones that divide by both 3 and 5 from the result.

like image 31
P.P Avatar answered Jul 14 '26 11:07

P.P



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!