Nhận 100 số palindrom


7

Tôi mới ở kịch bản và tôi có nhiệm vụ này, mà là để tìm 100 palindrome số với các thuật toán sau đây:

  1. Lấy số ngẫu nhiên gồm hai chữ số (lớn hơn 10)
  2. Đảo ngược số
  3. Tổng số và đảo ngược của nó
  4. Nếu kết quả của tổng là một số palindrom, hãy in nó. Nếu không, quay lại bước 2

Ví dụ:

  • Số bắt đầu: 75
  • Đảo ngược là 57
  • Tổng là 75 + 57 = 132

Vì 132 không phải là số palindrom, quay lại bước 2:

  • Đảo ngược là 321
  • 132 + 321 = 363
  • 363 là một số palindrom. In nó ra thiết bị xuất chuẩn!

Và cứ như vậy cho đến khi nó in ra 100 con số này.


Đây là những gì tôi có cho đến nay:

#! /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

Tìm kiếm giải pháp và giúp đỡ với kịch bản này!


Tôi có lỗi khi chạy tập lệnh của bạn vì vậy đã xóa một số vấn đề về cú pháp và quy ước trong mã. Xem nếu nó hoạt động bây giờ. Nếu đó là nhiệm vụ, tôi sẽ đề nghị bạn tự mình chiến đấu với nó.
mkc

8
@Ketan xin vui lòng không bao giờ, bao giờ sửa chữa các lỗi cú pháp trong câu hỏi. Điều đó nên được thực hiện trong một câu trả lời. Nếu bạn sửa lỗi, bản thân câu hỏi có thể trở nên vô nghĩa vì chúng ta sẽ không thể hiểu được lỗi của tập lệnh OP. Trong mọi trường hợp, chỉnh sửa của bạn vẫn để lại lỗi cú pháp khiến nó thậm chí còn ít hữu ích hơn :)
terdon

@terdon Ok, hiểu rồi
mkc

Câu trả lời:


1

Theo tôi hiểu trước tiên bạn cần nhận được số có hai chữ số

  • lớn hơn 10 và ít hơn 100
  • không chia cho 10 (không 20; 30; v.v.)
  • không palindrom (không 22; 33; v.v.)

Vì vậy, bạn có thể đạt được nó bằng cách

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

Bước tiếp theo để kiểm tra tổng số và đảo ngược của nó

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

OP muốn palindromes ("Nếu kết quả của tổng là số palindrom, hãy in nó. Nếu không, quay lại bước 2") và theo như tôi có thể nói, họ không hạn chế về việc số đó có chia hết cho 10. Đó là một mẹo thông minh để có được hai số chữ số mặc dù.
terdon

@terdon Đối với tôi không có ý nghĩa nào về số chia hết cho 10 giống như palindrom, thậm chí nó còn dễ dàng nhận được số có 2 chữ số bằng$RANDOM%100
Costas

1

Có nhiều lỗi cú pháp trong tập lệnh gốc của bạn. Ví dụ foo= barlà sai, không gian là quan trọng trong bash. Bạn cần foo=bar. Ngoài ra, để có được đầu ra của một lệnh, bạn không thể làm được foo=command, bạn cần đặt lệnh trong backticks, hoặc, tốt hơn foo=$(command). Đây là phiên bản hoạt động:

#!/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

Lưu ý rằng như vậy, kịch bản sẽ lặp lại số. Để có được các số duy nhất không ghi chú các dòng như được mô tả trong các nhận xét của tập lệnh.


1

Đây là một niềm vui. Tôi thích câu hỏi này. Tôi đã viết các chức năng sau đây để thực hiện nhiệm vụ và nó thực hiện công việc.

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
)

Có một vài điều đáng chú ý về điều này. Ở nơi đầu tiên, getoptsđược sử dụng để đảo ngược số. Chức năng chính của getoptslà phân tích các tùy chọn ngắn có thể hoặc không thể kết hợp với nhau - và do đó nó tạo ra một công cụ thuận tiện để lặp qua từng byte trong một chuỗi.

Tôi không thích $RANDchức năng của bashshell, nhưng có lẽ nó bảo thủ hơn rand()chức năng của tôi , nó chỉ làm nền cho một nhiệm vụ không hoạt động và gán PID không còn tồn tại của nó cho bất kỳ varname nào được lưu trữ trong đối số đầu tiên của nó. Khá rẻ, tôi sẽ thừa nhận.

Cấu casetrúc có thể dễ dàng đánh giá tất cả các khía cạnh của bài tập của bạn trong một bài kiểm tra đơn giản. Tôi làm:

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

Tôi đã có rất nhiều khó khăn với điều này lúc đầu. Lúc đầu, tôi đang làm những việc như:

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

Đó là một ý tưởng tồi . Việc bổ sung bỏ trốn ngay lập tức tăng số lượng lên kích thước mà chỉ số đếm chữ số là đủ để thổi bay mọi khả năng tìm thấy một bảng màu. Tôi đã loay hoay với date +%Snhưng tôi đoán rằng dù sao tôi cũng sẽ chạy một quy trình khác, tôi cũng có thể sử dụng bộ vi xử lý của nó. Và quá trình đó, trong trường hợp đó, cũng có thể chỉ là một null-op. Dù sao, phạm vi PID là đủ nhỏ để trị vì yếu tố chạy trốn khá nhiều lần, dường như.

Ví dụ: tôi sẽ chạy cái này ngay bây giờ và dán vào kết quả:

palindromes 76

ĐẦU RA

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

Có lẽ có một số bản sao trong đó - nó xảy ra, rõ ràng. Không nhiều. Tôi không biết đó có phải là vấn đề với bạn hay không, nhưng đây chỉ là một ví dụ về cách nó có thể được thực hiện.

Một lưu ý cuối cùng - chạy cái này dashnhanh hơn nhiều so với nó bash; mặc dù sự khác biệt dường như chỉ là một giây hoặc lâu hơn. Trong mọi trường hợp, nếu bạn sử dụng, dashbạn cần thay đổi rev() set -- "$1"dòng thànhset -- "${1#?}".

Tôi chỉ nhận ra có một yêu cầu gồm hai chữ số - mặc dù sự nghi ngờ của tôi là quy tắc cụ thể này là một nỗ lực để giữ cho bài tập không quá khó. Dù sao, chỉ nhận được một tập hợp con của một chuỗi là rất dễ thực hiện. Trong thực tế, đó là những gì tôi làm với r=khi tôi:

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

... luôn luôn chỉ định r một giá trị không bắt đầu bằng 0.

Đây là phiên bản rand()luôn gán một số có hai chữ số cho $1:

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

Bạn có thể áp dụng cùng một logic để bash's $RANDtất nhiên. Các $((var=(value)?(assign if true):(assign if false)))"nhà điều hành ternary sẽ làm việc với gần như bất kỳ bộ số nguyên. Ở đây tôi chỉ định nó là modulo 100 (về cơ bản là phần trăm) nếu giá trị đó lớn hơn mười, nếu không, tôi chỉ định đó là số thứ hai của hai chữ số trong đó số thứ nhất là số của các chữ số $!.

Chạy theo cách đó và kết quả của nó là một chút ít thú vị:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.