2014-09-03 2 views
-4

Сценарий принимает только один аргумент (назовите его n). Затем он поочередно добавляет и вычитает каждую цифру чисел от 1 до n.Bash script - головоломка

Например:

n = 12

1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 1 + 0 - 1 + 1 - 1 + 2

выходной : 5

#!/bin/bash 
number=$1 
result=1 
if ((number == 1 || number == 0)); then 
    echo 
    echo number: $number 
    echo 
else 
    for ((i = 1; i < number; i++)); do 
     if ((i < 10)); then 
      if ((i % 2 == 0)); then 
       let "result = result + i + 1" 
      else 
       let "result = result - i - 1" 
      fi 
     else 
      for ((i = 10; i <= number; i++)); do 
       if ((i < 100 && i >= 10)); then 
        let "result = result - i/10 + i%10" 
       else 
        let "result = result - i/100 + (i%100)/10 - (i/100)%10" 
       fi 
      done 
     fi 
    done 

    echo 
    echo result: $result 
    echo number: $number 
    echo 
fi 

он отлично работает для целых чисел от 0 до 9, но при п> 9 дает неправильный ответ.

Пожалуйста, исправьте мой сценарий и объясните мне, почему он ведет себя так.

PS Я новичок в Баш сценариев, так что я хотел бы видеть другое решение этой головоломки

PPS я знаком с Java

EDIT

Я установил код, и теперь он работает правильно

#!/bin/bash 
number=$1 
result=1 
if ((number == 1 || number == 0)); then 
    echo 
    echo number: $number 
    echo 
    else 
    for ((i = 1; i < number; i++)); do 
     if ((i < 9)); then 
      if ((i % 2 == 0)); then 
       let "result = result + i + 1" 
      else 
       let "result = result - i - 1" 
      fi 
     fi 
    done 
    for ((i = 10; i <= number; i++)); do 
     if ((i < 100)); then 
      let "result = result - i/10 + i%10" 
     else 
      if ((i % 2 == 0)); then 
       let "result = result - i/100 + (i%100)/10 - (i%100)%10" 
      else 
       let "result = result + i/100 - (i%100)/10 + (i%100)%10" 
      fi 
     fi 
    done 

    echo 
    echo result: $result 
    echo number: $number 
    echo 
fi 
+0

Это делает то, что вы хотите? Какое предпочтение оператора вы ожидаете здесь? 'result = result - i - 1' –

+0

Вы должны использовать' i <= number' ..., что означает, что скрипт фактически не ведет себя правильно по правильной причине для '0' через' 9'. –

+0

@KyleStrand да, это правда для ints> = 9, я отредактирую код – Sensei

ответ

4

Хорошо это должно работать извиняться, что я скучаю по читаемый вопрос ранее

number=$1 
MATSTR=""; 
for((i=1; i <= number; i++)); do 
     MATSTR="$MATSTR$i"; 
done; 
echo $MATSTR | sed -e 's/\(.\)\(.\)/\1-\2+/g' | sed 's/+$//' | bc 

Пояснение:

  • Для цикла, чтобы создать строку, объединяющую все числа от 1 до числа.
  • СЕПГ оператор заменяет каждые две цифр с 1-й цифрой минус второй цифрой плюс
  • SED удаляет завершающую плюс
  • Ьс вычисляет оператор
+0

Однако, я считаю, что это дает неправильный ответ, начинающийся с '10'. Если '10' должно быть' + 0', чтобы сделать '11 = 1', ответ должен быть' 5' для 'i = 10' not' 4'? –

+0

Спасибо и 10 должны быть '1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 1 + 0', что равно 4 – ShaneQful

+1

Теперь я вижу это! Используйте обе цифры от '10', а не просто' 10 = 0'.Вы прибили его - единственный способ сделать это - объединить все цифры, а затем спуститься по строке, добавляя и вычитая каждый. Молодцы с bc. –

1

После неправильного толкования вопроса (или непонятного вопроса) ответ принял лишь незначительные корректировки. Решение жала, вероятно, самый простой подход с использованием modulo для togget +/-:

#!/bin/bash 

declare -i num=$1 
declare -i res=0 
str="" 

[ "$num" -gt 1 ] || { 
    printf "\n Error: invalid input. usage: %s int (greater than 1)\n\n" "${0//*\//}" 
    exit 1 
} 

for ((i = 1; i <= $num; i++)); do # create the string of digits 
    str="${str}${i}" 
done 

printf "\n Calculations:\n\n" 

for ((i = 0; i < ${#str}; i++)); do # walk down the string adding/subtracting each digit 
    if [ $((i % 2)) -eq 0 ]; then 
     ((res+=${str:$i:1})) 
     printf " res + %3s = %3s\n" "${str:$i:1}" "$res" 
    else 
     ((res-=${str:$i:1})) 
     printf " res - %3s = %3s\n" "${str:$i:1}" "$res" 
    fi 
done 

printf "\n Final Result: %s\n\n" "$res" 

exit 0 

выход:

$ ./puzzle.sh 12 

Calculations: 

    res + 1 = 1 
    res - 2 = -1 
    res + 3 = 2 
    res - 4 = -2 
    res + 5 = 3 
    res - 6 = -3 
    res + 7 = 4 
    res - 8 = -4 
    res + 9 = 5 
    res - 1 = 4 
    res + 0 = 4 
    res - 1 = 3 
    res + 1 = 4 
    res - 1 = 3 
    res + 2 = 5 

Final Result: 5 
+0

, начиная с 10, он должен разбить число на 1 и 0, 11 = 1 и 1 и т. Д. – Sensei

+0

Хорошо, что сделано, см. Нижний ответ. Это хороший трюк. –

+0

все еще работает неправильно, для 'n = 99' выход должен быть' -40' вместо '50' – Sensei

2

Вот ваше оригинальное решение, но с исправлением ошибок (в комментариях). Конечно, он по-прежнему не работает для number > 99.

#!/bin/bash 
number=$1 
result=0           # Don't start at 1!! 
if ((number == 1 || number == 0)); then 
    echo 
    echo number: $number 
    echo 
else 
    for ((i = 1; i <= number; i++)); do   # <=, not < 
     if ((i < 10)); then      # < 10, not < 9 
      if ((i % 2 == 0)); then 
       let "result = result - i"   # subtraction! Also, the +1 was unnecessary 
      else 
       let "result = result + i"   # addition! 
      fi 
     else 
      if ((i < 100 && i >= 10)); then 
       let result=result-i/10+i%10 
      else 
       let "result=result-i/100+(i%100)/10-(i/100)%10" 
      fi 
     fi 
    done 

    echo 
    echo result: $result 
    echo number: $number 
    echo 
fi 
+0

@Fizunik Я объяснил, как работает ваш код (более или менее случайно). Я также исправил его, чтобы он работал разумным, в основном читаемым и семантически правильным образом. Почему вы предполагаете, что это не работает, а не пытается это сделать? –

+0

Да, извините. Я скопировал его, но не спас его, когда я его тестировал. Виноват. Я вижу вашу точку там. – Sensei