पात्रों और संख्याओं के सभी संभावित संयोजन


13

इसलिए मैं निचले और ऊपरी मामलों के पात्रों और संख्याओं के सभी संभावित संयोजनों को उत्पन्न करना चाहता हूं जो 5 वर्ण स्ट्रिंग बना सकते हैं।

संभावनाएँ: a..z, A..Z और 0..9।

क्या इसको करने का कोई सुंदर तरीका है?


1
क्या आप खुद को ASCII या लैटिन स्क्रिप्ट तक सीमित रखना चाहते हैं? एक्सेंट (é, â ...) जैसे डायक्टिक्स के बारे में क्या?
स्टीफन चेज़लस

अनुवर्ती कार्रवाई के लिए धन्यवाद। स्पष्टीकरण के लिए अपडेट की गई मूल पोस्ट।
शाम

क्या वास्तव में इसे बकवास होने की आवश्यकता है? Perl या awk जैसी भाषा करेंगे?
terdon

1
तो फिर सिर्फ बैश से पर्ल या पायथन को क्यों नहीं बुलाया जाए? विशेष रूप से perl, यह एक लाइनर के रूप में उपयोग करने के लिए बहुत आसान है।
terdon

2
क्या आप सीखने की कोशिश कर रहे हैं या सिर्फ परिणाम चाहते हैं? दूसरे मामले में बहुत सारे प्रोग्राम हैं जो जॉइन द रिपर ( john) और जैसे काम करते हैं, जो आपको बहुत संभावनाएं देंगे।
योइमोसो

जवाबों:


13

यहां एक बैश समाधान है जो वांछित लंबाई को पैरामीटर के रूप में लेता है (आप permute 5अपने मामले में करेंगे):

#!/bin/bash
charset=({a..z} {A..Z} {0..9})
permute(){
  (($1 == 0)) && { echo "$2"; return; }
  for char in "${charset[@]}"
  do
    permute "$((${1} - 1 ))" "$2$char"
  done
}
permute "$1"

यह दर्द से धीमा है, हालांकि। हिम्मत मैं सी की सिफारिश? https://youtu.be/H4YRPdRXKFs?t=18s

#include <stdio.h>

//global variables and magic numbers are the basis of good programming
const char* charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
char buffer[50];

void permute(int level) {
  const char* charset_ptr = charset;
  if(level == -1){
    puts(buffer);
  }else {
   while(buffer[level]=*charset_ptr++) {
    permute(level - 1);
   }
  }
}

int main(int argc, char **argv)
{

  int length;
  sscanf(argv[1], "%d", &length); 

  //Must provide length (integer < sizeof(buffer)==50) as first arg;
  //It will crash and burn otherwise  

  buffer[length]='\0';
  permute(length - 1);
  return 0;
}

चलाओ:

make CFLAGS=-O3 permute && time ./permute 5 >/dev/null #about 20s on my PC

उच्च-स्तरीय भाषाएँ जानवर-मजबूर (जो मूल रूप से आप क्या कर रही हैं) को चूसती हैं।


@ स्टीफन चेज़लस उस संपादन के लिए आपका बहुत-बहुत धन्यवाद। मैं गंदे लिख रहा था, "उचित" को अनदेखा करते हुए उद्धृत करना क्योंकि इस मामले में इसकी आवश्यकता नहीं है, लेकिन मैं शॉर्टकट के लिए बहुत आभारी हूं!
PSkocik

मैंने आपके bashसमाधान की कोशिश की । यह बहुत अच्छा है; मुझे बहुत पसंद है। लगभग 24 घंटे तक काम किया। इससे पहले कि मैंने देखा कि मेरा सिस्टम पूरी तरह से बंद था। `अजगर के साथ कुछ इसी तरह की कोशिश की; एक समान परिणाम के साथ, हालांकि यह काफी तेज था।
आवाज

8

में bash, आप कोशिश कर सकते हैं:

printf "%s\n" {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}

लेकिन वह हमेशा के लिए ले जाएगा और आपकी सभी मेमोरी का उपयोग करेगा। सबसे अच्छा होगा एक और उपकरण का उपयोग करें perl:

perl -le '@c = ("A".."Z","a".."z",0..9);
          for $a (@c){for $b(@c){for $c(@c){for $d(@c){for $e(@c){
            print "$a$b$c$d$e"}}}}}'

खबर है कि 6 x 62 5 बाइट्स हैं, इसलिए 5,496,796,992 हैं।

आप उसी लूप को अंदर कर सकते हैं bash, लेकिन bashपश्चिम में सबसे धीमा शेल होने के नाते , इसमें घंटे लगेंगे:

export LC_ALL=C # seems to improve performance by about 10%
shopt -s xpg_echo # 2% gain (against my expectations)
set {a..z} {A..Z} {0..9}
for a do for b do for c do for d do for e do
  echo "$a$b$c$d$e"
done; done; done; done; done

(मेरे सिस्टम पर, जो कि 700 kiB / s पर 20MiB / s perlसमतुल्य के विपरीत आउटपुट करता है)।


मुझे यह भी लगता है कि यदि आप इसे किसी फ़ाइल में आउटपुट करने का कोई तरीका जोड़ते हैं तो यह उत्तर में जोड़ देगा; शायद जैसा कि यह उत्पन्न हो रहा है इसलिए यह आपकी रैम को नष्ट नहीं करता है, या इसके बाद यह सब राम में कैश्ड हो गया है
Hellreaver

2
@ हेलराइवर, वे सभी एक फ़ाइल में लिखते हैं (स्टैडआउट करने के लिए, जो भी फ़ाइल ओपन होती है; अगर टर्मिनल में चलती है, जैसे डिवाइस फ़ाइल /dev/pts/something; और आप इसे शेल पुनर्निर्देशन ऑपरेटर के साथ बदल सकते हैं), मेमोरी नहीं, बल्कि पहले एक तार इसे आउटपुट करने से पहले मेमोरी में पूरा आउटपुट (स्टडआउट पर फाइल को खोलने के लिए)।
स्टीफन चेज़लस

4

यहां 5 जीबी मेमोरी को चॉइस किए बिना पूरी तरह से बैश में करने का एक तरीका है:

for c1 in {A..Z} {a..z} {0..9}
do
    for c2 in {A..Z} {a..z} {0..9}
    do
        for c3 in {A..Z} {a..z} {0..9}
        do
            for c4 in {A..Z} {a..z} {0..9}
            do
                for c5 in {A..Z} {a..z} {0..9}
                do
                    printf "%s\n" "$c1$c2$c3$c4$c5"
                done
            done
        done
    done
done

2

यह बैश संस्करण अभी भी पर्ल के समान तेज़ नहीं है, लेकिन यह पाँच नेस्टेड छोरों की तुलना में चार गुना तेज़ है:

printf -vtwo "%s " {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}
for three in {{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}{{a..z},{A..Z},{0..9}}; do
    printf "$three%s\n" $two;
done

1

आप उपयोग कर सकते हैं crunch(जो कम से कम काली वितरण पर उपलब्ध है)।

crunch 5 5 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890

1

खैर ... सुरुचिपूर्ण ?, हाँ (बस एक तेज़ नमूना):

eval echo $(printf "%s" '{{a..z},{A..Z},{0..9}}'{,,} )

यह पूर्ण अभिव्यक्ति सबसे अधिक संभावना आपके कंप्यूटर को अवरुद्ध करेगी:

eval echo $(printf "%s" '{{a..z},{A..Z},{0..9}}'{,,,,} )

एक गैर-अवरोधक विकल्प कई छोरों का उपयोग करना है:

nl=$'\n'; tab=$'\t'
n=${1:-3}
eval set -- "$2"

eval "varnames=($(echo {a..z}))"

for i in "${varnames[@]:0:$n}"; do
    header+='for '"$i"' do '
    middle+='$'"$i"
    traile+="done; "
done

loop="${header}${nl}    printf %s \"$middle\";${nl}$traile"
#echo "$loop"
eval "$loop"

इसे कॉल करें जैसे:

./script 3 '{a..z} {A..Z} {0..9}'

जहाँ पहला तर्क वर्णों की संख्या है और दूसरा प्रयुक्त वर्णों की सूची (स्थान अलग) है।

वह loopस्क्रिप्ट के साथ एक चर ( ) का निर्माण करेगा और अंतिम ईवैल्यू उस स्क्रिप्ट को निष्पादित करेगा। उदाहरण के लिए:

$ ./script 5 '{a..z} {A..Z} {0..9}'

का मान loopहोगा:

for a do for b do for c do for d do for e do
    echo "$a$b$c$d$e";
done; done; done; done; done;

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.