100개의 회문을 얻으세요

100개의 회문을 얻으세요

저는 스크립팅을 처음 접했고 제 임무는 100개를 찾는 것입니다.회문다음 알고리즘을 사용하는 숫자:

  1. 두 개의 난수를 얻습니다(10보다 큼).
  2. 역방향 숫자
  3. 숫자와 그 역수 더하기
  4. 합의 결과가 회문이면 인쇄하십시오. 그렇지 않으면 2단계로 돌아가세요.

예를 들어:

  • 시작 수량: 75
  • 뒷면은 57입니다
  • 합계는 75+57 = 132입니다.

132는 회문 번호가 아니므로 2단계로 돌아갑니다.

  • 그 반대는 321이다.
  • 132 + 321 = 363
  • 363은 회문수이다. 표준 출력으로 인쇄하세요!

그리고 그러한 숫자가 100개까지 인쇄될 ​​때까지 계속됩니다.


이것이 내가 지금까지 가지고 있는 것입니다:

#! /bin/bash

CONT=0
while [ $CONT -lt 100 ] 
do
    NUM= $RANDOM
    while [ $SUM -ne $SUMINV ] 
    do

        echo $NUM > file.txt
        INV= rev file.txt
        SUM= `expr[ $NUM + $INV ]`
        echo $SUM > file2.txt
        SUMINV= rev file2.txt
        NUM= $SUM
    done
    echo $NUM
    CONT=`expr $CONT + 1`
done

이 스크립트에 대한 솔루션과 도움을 찾고 있습니다!

답변1

제가 알기로는 먼저 두 자리 숫자를 받아야 합니다.

  • 10보다 크다 100보다 작다
  • 10으로 나누지 않음(20, 30 등은 아님)
  • 회문이 아님(22,33 등이 아님)

그래서 당신은 그것을 통해 도달 할 수 있습니다

while :
do
  a=$[$RANDOM%10]
  b=$[$RANDOM%10]
  if [ $a -ne $b -a $a -ne 0 -a $b -ne 0 ]
  then
    NUM="$a$b"
    RNUM="$b$a"
    break
  fi
done

다음으로 숫자의 합과 반전을 확인하세요.

while :
do
  NUM=$[$NUM+$RNUM]
  RNUM=$(printf "%d" $NUM | rev)
  if [ $NUM -eq $RNUM ]
  then
    echo $NUM
    break
  fi
done

답변2

원본 스크립트에 다양한 구문 오류가 있습니다. 예를 들어 foo= bar, Bash에서는 공백이 중요합니다. 당신은해야합니다 foo=bar. 또한 명령의 출력을 얻으려면 이 작업을 수행할 수 없으며 foo=command명령을 백틱으로 묶어야 합니다 foo=$(command). 또는 더 나은 방법은 다음과 같습니다. 작업 버전은 다음과 같습니다.

#!/usr/bin/env bash
CONT=0

## This array will hold the numbers we've seen
## uncomment this line for unique numbers
#declare -a seen;
while [ "$CONT" -lt 100 ] 
do
    ## Get a random number
    NUM=$RANDOM
    ## Make sure it is < 100
    let "NUM %= 100"
    ## Make sure the number is more than 10
    while [ "$NUM" -le 10 ]
    do
        NUM=$((NUM+1))
    done
    ## In case the addition made it longer than two digits
    NUM="${NUM:0:2}"
    ## Make sure the number does not end in 0
    ## If it does, we will get an error when
    ## attempting to add it. Bash doesn't
    ## like leading 0s. 
    [[ $NUM =~ 0$ ]] && let NUM++
    ## Sum the number and its reverse
    SUM=$((NUM+$(rev <<<$NUM)));

    ## Is this a palindrome?
    if [ "$SUM" = "$(rev <<<$SUM)" ]
    then
        ## You did not say if you wanted 100 different
        ## numbers. If so, uncomment these lines
        #let seen[$SUM]++
        ## If this number has not been seen before
        #if [ "${seen[$SUM]}" -eq 1 ]
        #   then
        ## print it
        echo $SUM
        ## increment the counter
        let CONT++
        #fi
    fi
done

스크립트는 숫자를 있는 그대로 반복합니다. 고유 번호를 얻으려면 스크립트 주석에 설명된 대로 이 줄의 주석 처리를 제거하세요.

답변3

이것은 흥미 롭습니다. 나는 이 질문을 좋아한다. 작업을 수행하기 위해 다음 함수를 작성했고 작업이 완료되었습니다.

palindromes() (
rev()   while getopts : o "-$1" ||
        ! r="${2#"${2%%[1-9]*}"}"
        do set -- "$1" "$OPTARG$2"
        done
rand()  { : & : "$(($1=$!))"; }

[ "$1" -gt 10 ] || exit
n=$1; set --
while OPTIND=1; rev "$n"
        case "$#.$n.$r"                              in
        (100.*) ! printf '%s\t%s\t%s\t%s\t%s\n' "$@" ;;
        (*.$r.$n) set -- "$@" "$n"; rand n           ;;
        (*)       n=$((${n#-}+${r%-}))               ;;
esac; do :; done
)

이에 대해 주목할 만한 몇 가지 사항이 있습니다. 첫째, getopts숫자를 반전시키기 위한 것입니다. 의 주요 기능은 getopts모두 함께 연결될 수도 있고 그렇지 않을 수도 있는 짧은 옵션을 구문 분석하는 것입니다. 따라서 문자열의 각 바이트를 반복하는 데 편리한 도구가 됩니다.

$RAND나는 쉘 의 기능을 별로 좋아하지 않지만 백그라운드에서 아무 작업도 수행하지 않고 첫 번째 인수에 저장된 varname에 무효화된 PID를 할당하는 bash내 기능보다 더 보수적일 것입니다 . rand()인정해요, 꽤 저렴해요.

case구조를 사용하면 간단한 테스트를 통해 과제의 모든 측면을 쉽게 평가할 수 있습니다. 나는 다음을 원한다:

case "$#.$n.$r" in 
(100*) all done; printf %s\\n "$@";; 
(*$r.$n) palindrome; set -- "$@" "$n";;
(*) no luck; $n+$r; go again;;
esac

처음에는 이것 때문에 많은 어려움을 겪었습니다. 처음에 나는 다음과 같은 일을 하고 있었습니다.

(*$r.$n) set -- ...; n=$((n+1))

그건나쁜아이디어. 런어웨이 덧셈은 단순히 숫자를 세는 것만으로도 회문을 찾을 가능성을 제거하기에 충분할 정도로 숫자를 즉시 ​​증가시킵니다. 엉망이 되었지만 date +%S다른 프로세스를 실행하려면 그냥 PID를 사용하는 편이 낫겠다고 생각했습니다. 이 경우 프로세스가 아무런 작업도 수행하지 않을 수도 있습니다. 그럼에도 불구하고 PID 범위는 거의 매번 폭주 요인을 제어할 수 있을 만큼 작습니다.

예를 들어 지금 실행하고 결과를 붙여넣겠습니다.

palindromes 76

산출

484     29292   49294   69296   89298
215512  50605   90609   446644  886688
123321  52625   92629   468864  663787366
134431  54645   94649   881585188       7667585634365857667
145541  23432   43434   63436   83438
147741  24442   44444   64446   84448
158851  25452   45454   65456   85458
169961  13231   46464   66466   86468
49985258994     27472   47474   67476   87478
14355341        28482   48484   68486   88488
395593  29492   49494   69496   89498
219912  121121  11244211        441144  881188
125521  165561  15522551        463364  7365409856589045637
136631  211112  17858768886785871       485584  893974888888479398
147741  23632   43634   63636   83638
149941  24642   44644   64646   84648
523325  25652   45654   65656   85658
567765  13331   46664   66666   86668
2358532 27672   47674   67676   87678
2236322 28682   48684   68686   88688

아마도 사기꾼이 있을 것입니다. 분명히 그런 일이 발생합니다. 별로. 이것이 당신에게 문제가 되는지 모르겠지만, 이것은 그것이 어떻게 이루어질 수 있는지를 보여주는 예일 뿐입니다.

마지막 참고 사항 - 차이가 1초 정도인 것처럼 보이지만 이를 실행하는 것이 dash에서 실행하는 것보다 훨씬 빠릅니다 . bash어떤 경우 에라도,당신이 그렇게한다면사용하려면 줄을 다음으로 변경 dash해야합니다 .rev() set -- "$1"set -- "${1#?}".

나는 방금 두 자리 요구 사항이 있다는 것을 깨달았습니다. 비록 이 특정 규칙이 과제가 너무 어려워지는 것을 방지하기 위한 것이라고 생각합니다. 어쨌든, 문자열의 하위 집합만 얻는 것은 쉽습니다. 실제로 이것은 r=다음 상황에서 내가 한 일입니다.

r="${2#"${2%%[1-9]*}"}"

r...항상 0으로 시작하지 않는 값을 할당합니다 .

rand()항상 두 자리 숫자를 할당하는 버전은 다음과 같습니다 $1.

rand() { : & set -- "$1" "$!" "$(($!%100))"
         : "$(($1=($3>10?$3:${#2}$3)))"
}

물론 bash's'에도 동일한 논리를 적용할 수 있습니다. $RAND삼항 $((var=(value)?(assign if true):(assign if false)))"연산자는 거의 모든 정수 집합에 대해 작동합니다. 여기서는 모듈로 100을 할당합니다.(기본적으로 백분위수)값이 10보다 크면 두 자리 중 두 번째 자리로 지정합니다. 여기서 첫 번째 자리는 count 의 자리 수입니다 $!.

이런 식으로 실행하면 결과가 덜 흥미로워집니다.

333     66      484     1111    4884
77      88      99      121     121
363     484     77      4884    44044
88      99      121     121     363
484     1111    4884    88      8813200023188
99      121     121     363     484
1111    4884    44044   8813200023188   99
44      55      66      77      44
99      121     121     363     484
424     11      33      44      55
66      77      88      99      121
22      33      22      55      66
77      88      99      121     121
33      44      55      33      77
88      99      121     121     363
44      55      66      77      44
99      121     121     363     484
55      66      77      88      99
55      121     363     484     1111
66      77      88      99      121

관련 정보