开发者

How can I shift digits in bash?

I have a homework assignment that is asking to shift a decimal number by a specified amount of digits. More clearly this bash script will take two input arguments, the first is the number(maximum 9 digits) that the shift will be performed on and the second is the number(-9 to 9) of digits to shift. Another requirement is that when a digit is shifted off the end, it should be attached to the other end of the number. One headache of a requirement is that we cannot use control statements of any kind: no loops, no if, and switch cases.

Example: 12345 3 should come out to 345000012 and 12345 -3 should be 12345000

I know that if I mod 12345 by 10^3 I get 345 and then if I divide 12345 by 10^3 I get 12 and then I can just concatenate those two variables together to get 34512. I am not quite sure if that is exactly correct but that is开发者_运维百科 the closest I can get as of now. As far as the -3 shift, I know that 10^-3 is .001 and would work however when I try using 10^-3 in bash I get an error.

I am just lost at this point, any tips would be greatly appreciated.

EDIT: After several hours of bashing (pun intended) my head against this problem, I finally came up with a script that for the most part works. I would post the code right now but I fear another student hopelessly lost might stumble upon it. I will check back and post what I came up with in a week or two. I was able to do it with mods and division. Thank you all for the responses, it really helped me to open up and think about the problem from different angles.


Here's a hint:

echo ${string:0:3}
echo ${#string}

Edit (2011-02-11):

Here's my solution. I added some additional parameters with defaults.

rotate-string ()
{
    local s=${1:-1} p=${2:--1} w=${3:-8} c=${4:-0} r l
    printf -vr '%0*d' $w 0    # save $w zeros in $r
    r=${r//0/$c}$s            # change the zeros to the character in $c, append the string
    r=${r: -w}                # save the last $w characters of $r
    l=${r: -p%w}              # get the last part of $r ($p mod %w characters)
    echo "$l${r::w-${#l}}"    # output the Last part on the Left and the Right part which starts at the beginning and goes for ($w minus the_length_of_the_Left_part) characters
}

usage: rotate-string string positions-to-rotate width fill-character

example: rotate-string abc -4 9 =

result: ==abc====

Arguments can be omitted starting from the end and these defaults will be used:

  • fill-character: "0"
  • width: 8
  • positions-to-rotate: -1
  • string: "1"

More examples:

$ rotate-string
00000010
$ rotate-string 123 4
01230000

Fun stuff:

$ for i in {126..6}; do printf '%s\r' "$(rotate-string Dennis $i 20 .)"; sleep .05; done; printf '\n'

$ while true; do for i in {10..1} {1..10}; do printf '%s\r' "$(rotate-string : $i 10 .)"; sleep .1; done; done

$ while true; do for i in {40..2} {2..40}; do printf '%s\r' "$(rotate-string '/\' $i 40 '_')"; sleep .02; done; done

$ d=0; while true; do for i in {1..10} {10..1}; do printf '%s\r' "$(rotate-string $d $i 10 '_')"; sleep .02; done; ((d=++d%10)); done

$ d=0; while true; do for i in {1..10}; do printf '%s\r' "$(rotate-string $d $i 10 '_')"; sleep .2; ((d=++d%10)); done; done

$ shape='▁▂▃▄▅▆▇█▇▆▅▄▃▂▁'; while true; do for ((i=1; i<=COLUMNS; i++)); do printf '%s\r' "$(rotate-string "$shape" $i $COLUMNS ' ')"; done; done


In the absence of control structures, you need to use recursion, with index values as "choice selections", which is how functional programming often works.

#!/bin/sh
#
# cshift NUMBER N
cshift() {
  let num=10#$1
  num=`printf '%09d' $num`
  lshift="${num:1:8}${num:0:1}"
  rshift="${num:8:1}${num:0:8}"
  next=( "cshift $lshift $(($2 + 1))" "echo $num" "cshift $rshift $(( $2 - 1 ))" )
  x=$(( $2 == 0 ? 1 : $2 < 0 ? 0 : 2 ))
  eval "${next[x]}"
}

cshift $1 $2

and, the testing:

$ for ((i=-9;i<=9;i++)); do cshift 12345 $i ; done
000012345
500001234
450000123
345000012
234500001
123450000
012345000
001234500
000123450
000012345
500001234
450000123
345000012
234500001
123450000
012345000
001234500
000123450
000012345

You can also do some math on the indexes and avoid the recursion, but I don't mind making the computer work harder so I don't have to. It's easy to think of how to do the shift by one in either direction, and then I use an evaluated choice that is selected by the signum of the shift value, outputting a value and stopping when the shift value is zero.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜