Napisz program, który wykonuje kombinację liter typu brute force, dopóki nie zostanie znalezione słowo „hasło”

16

Program powinien wypisać każdą kombinację liter (małe lub wielkie litery, to nie ma znaczenia) w kolejności alfabetycznej. Musi zaczynać się aod ostatniej wydrukowanej kombinacji password.

Dane wyjściowe powinny być:

a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ... passwora passworb passworc password
ST3
źródło
2
Czy separatory muszą być spacjami, czy mogę używać znaków nowej linii?
Ilmari Karonen,
Tak, możesz, to tylko niewielka zmiana.
ST3

Odpowiedzi:

32

Perl, 19 znaków

say for a..password

Wykorzystuje znaki nowej linii jako ograniczniki, zgodnie z powyższym wyjaśnieniem. Uruchom z perl -M5.010(lub po prostu perl -E 'say for a..password'), aby włączyć funkcję Perl 5.10+ say. W przeliczeniu na meta nie liczy się to jako dodatkowe znaki.

(Jeśli nalegasz na spacje jako ograniczniki, $,=$";say a..passwordjest on tylko o dwa znaki dłuższy. Jednak jest również bardzo powolny i marnuje pamięć, do tego stopnia, że ​​nie nadaje się do użycia w praktyce, ponieważ próbuje wydrukować całą listę w pamięci przed wydrukowaniem.)

Ilmari Karonen
źródło
18

Ruby, 33 znaki (optymalna, ale dłuższa wersja)

?a.upto('password'){|c|$><<c+' '}

Lubię 'a'.upto('password'); mówi ci dokładnie, co robi. Ruby jest taka wspaniała i wyrazista.:D

Oczywiście print c,' 'byłoby również znacznie jaśniejsze, ale przy użyciu$> dwóch znaków jest krótsze.

Ruby, 29 25 znaków (wersja wolna)

$><<[*?a..'password']*' '

Ten jest krótszy, ale drukuje wszystkie tokeny jednocześnie, więc uruchomienie zajmuje dużo czasu!

Klamka
źródło
1
Fajnie, zwłaszcza pierwsza.
Cary Swoveland,
W wersji wolnej (?a..'password').to_amożna skrócić do[*?a..'password']
Paul Prestidge 30.09.13
6

Perl, 33 32 24 znaków

Rozwiązanie w 32 znakach:

$_=a;print$_++,$"until/passwore/

Niewiele do powiedzenia na ten temat. Mógłbym zmniejszyć to do 27 znaków, gdybym mógł użyć znaków nowej linii zamiast spacji do oddzielenia wpisów.

Ilmari Karonen wskazuje, że ..połączenia wewnętrzne ++, więc lepszym rozwiązaniem (25 znaków) byłoby:

print$_,$"for a..password

Korzystając z opcji wiersza polecenia Perla, oto równoważne 24-znakowe rozwiązanie:

perl -l40e 'print for a..password'

Zasady liczenia flag perla są tutaj, dla tych, którzy ich nie znają.

Oczywiście 21-znakowe rozwiązanie Ilmari jest jeszcze krótsze, ale wymaga komputera, który może przydzielić tablicę 129 052 722 140 ciągów.

chlebak
źródło
Czy .$"zamiast ," "uratować postać?
Pan Llama,
Tak, całkowity nadzór z mojej strony. Dzięki.
breadbox
6

Perl 6, 20 znaków

say "a".../password/

Nie potrzebujesz innych rzeczy

Demayl
źródło
5

Python 2, 91

b=lambda n:n*' 'and b(n/26-(n%26<1))+chr(~-n%26+97)
i=0
exec"i+=1;print b(i);"*129052722140
feersum
źródło
4

PHP 38 37 36 znaków

<?for($w=a;$w<passwore;)echo$w++,~ß;

Musisz ustawić kodowanie na ISO 8859-1 i wyłączyć ostrzeżenia.

lortabak
źródło
Nie testowałem tego, ale czy naprawdę to robi ???
ST3
@ ST3 To prosta pętla. Zmienna $wjest początkowo ustawiona na „a”, a następnie jest zwiększana, aż osiągnie pierwszą wartość po „haśle” (ostatni ciąg nie jest drukowany).
lortabac,
3
@ ST3 Jest to zwykła forpętla. W tym kodzie nie ma nic dziwnego, z wyjątkiem ostatnich 2 znaków, które są nieco odwróconymi spacjami. W każdym razie tak, przetestowałem to do krótszego słowa.
lortabac,
1
@ ST3 Oto test od passwoqsdo password. Ponieważ kodowanie w codepad nie jest zgodne z ISO 8859-1, musiałem zastąpić go spacją.
lortabac
1
Możesz uratować postać $w<passworezamiast $w!=passwore.
Decent Dabbler
2

Rubin (40 znaków)

Interpretuj ciąg liter az jako liczbę w podstawie 26, gdzie a = 1, b = 2, ..., z = 26.

„Hasło” można więc traktować jako liczbę N =

16*(26**7) + 
1*(26**6) + 
19*(26**5) + 
19*(26**4) + 
23*(26**3) + 
15*(26**2) + 
18*(26**1) + 
4*(26**0)

Jeśli pozwolimy s = "a"(to znaczy: 1) i wykonamy (N-1) wywołania do s.succ!, s będzie "password"(N). Innymi słowy, N = 1 + (N-1).

For an example that will run more quickly, to prove the calculation of N is correct, consider "pass" as the target, where N is

16*(26**3) + 
1*(26**2) + 
19*(26**1) + 
19*(26**0)

and

s = "a"
(N-1).times { s.succ! }
puts s #== "pass"

Since we want to print "a" too, we need

s = "`"
N.times { print(s.succ! + " ") }

So back to the full "password". N = 129052722140, leaving:

s=?`;0x1e0c2443dc.times{$><<s.succ!+" "}

I hunted for a more compact form of 129052722140 == 0x1e0c2443db but couldn't find one.

(Updated to fix the lack of printing "a", thanks to Cary.)

Adam Prescott
źródło
1
Adam, that must have been you in my mind-meld. Don't you want s to start one before 'a'?
Cary Swoveland
I think what you're getting at is that I've used N instead of N-1 in my iterations! Thanks, I'll edit to fix. (Although 129052722140 is an interesting number to Google :).)
Adam Prescott
1
0x1e0c2443db is just as many chars as 129052722139.
steenslag
What I meant was that if s=?a, s.succ! starts at 'b'`.
Cary Swoveland
1
With s=?a and N-1 you get 'b c...password'; with s =<backtick> and N you get 'a b...password'. The SO requested the output to begin with 'a'. That's all.
Cary Swoveland
2

Javascript, 73

Here is a 73 character version of @Briguys' code, which prints only letter combinations

for(i=s=0;1982613533018>i++;s=i.toString(36))/\d/.test(s)||console.log(s)

C5H8NNaO4
źródło
2

APL(Dyalog), 46 34

{∇{'PASSWORD '≡⍞←⍵:→⋄⍵}¨⎕A∘.,⍵}' '

Theoretically, it would print until PASSWORD, but I encountered a work space full error after ZZZZ: 5-dimensional array is just too awesome.

EDIT: Must have been too long since I last fiddled with APL. How dare I missed the identity comparision ()!!!

Explanation

{...}: Declares a function which...
⎕A∘.,⍵: Takes the outer product over concatenation (Every combination of an element of the left operand concatenated with an element of the right operand, just like Cartesian Product) between the 26 uppercase alpha (⎕A) and the argument ()

{...}¨: And for each element of the resulting set, plug that into a function which...
⍞←⍵: prints it out
'PASSWORD '≡ and compare it with 'PASSWORD '
: If the comparison returns true (1), then abort the program.
: Else just return the printed string.

: Finally, the outer function recurse itself.

(Then you are taking outer product over concat between the 26 alpha and the 26 alpha, which gives all the 2-letter combinations, and then outer product over concat between the 2-letter combinations and the 26 alpha, etc... Until you reach PASSWORD which triggers the abort)

' ': The spark!! That kick-start the recursive function with the space character.

TwiNight
źródło
2

Python 2 - 153 152 151 149 bytes

from itertools import*;R=range
for l in iter(chain(*[product(*((map(chr,R(65,91)),)*n))for n in R(1,9)]).next,tuple("passwore")):print ''.join(l)

Saved one byte by using UPPERCASE and one by using newlines instead of spaces.

pppery
źródło
1

Golfscript 41

For lack of 'z'+1 == 'aa' logic Golfscript can't win this one.

168036262484,(;{27base{96+}%' '+.96?0<*}%
  • 168036262484, create array from 0 to 168036262483
  • (; drop the 0
  • { .. }% iterate over array
  • 27base convert element to base 27 array
  • {96+}% add 96 to each digit
  • ' '+ convert to string and add a space to the end
  • .96?0<* truncate string to zero if it contains char 96
aaaaaaaaaaaa
źródło
1

In Ruby, 39 40.

a=&`
0x1e0c2443dc.times{$><<a.succ!+' '}

..or 129052722140. (Edit: formerly I had 129052722. I had lost some digits cutting and pasting. Previous hex (0x7B13032) was for incorrect number.). Borrowed a=?` from @Doorknob to saves a character.

Cary Swoveland
źródło
I tried to fix the a=?` thing, it looks kinda weird and has an extra space at the end but at least it works :P
Doorknob
So where does the number 129052722 come from? By my calculation, that would seem to give you the range "a" to "kwkokg" ... a bit small.
breadbox
@Breadbox I calculated that number with the following method (sorry for the formatting, but comments have limitations, eh?): ORD_BASE_ASCII = 'a'.ord-1; def nbr(word); len = word.size; word.split('').inject(0) {|t,c| offset = c.ord - ORD_BASE_ASCII; t + offset*(26**(len -= 1))}; end It's easy to confirm this is correct by just printing out some sequences.
Cary Swoveland
@breadbox You were right. See edit. Method I gave in comment is OK.
Cary Swoveland
Fencepost errors. Your script is calculating using a=1..z=26. You need to calculate a=0..z=25 to get the right count. Removing the -1 from the first line, you'll get 120699639557, which (adding one for the zeroth entry) matches my calculation.
breadbox
1

Javascript: 57 56 characters (thanks C5H8NNaO4)

Here's a solution that includes numbers as possible characters ("0", "1", "2", .., "passwor9", "passwora", "passworb", "passworc", "password")

for(i=-1;i++<1982613533017;console.log(i.toString(36)));

Here's a fiddle for testing (with only the last 100 iterations so it doesn't lock up your browser).

Briguy37
źródło
3
This solution is wrong, it doesn't follow the specification.
Doorknob
@Doorknob - Yes, I mentioned that in my answer. It still prints all cases from the original requirements, but prints all alpha-numeric cases as well.
Briguy37
Also, after re-reading the question, if I set i to 9 in my code, it would meet ALL the question's requirements except for his example output, which he has already given an exception for (and it would bring the code to 56 characters).
Briguy37
@Briguy37 The spec says print every **letter** combination Anyway, save a character: {} -> ;
C5H8NNaO4
@C5H8NNaO4: Which letter combination does my solution not print? Thanks for the tip!
Briguy37
1

Haskell, 101

main=putStrLn.concat.takeWhile(/="passwore ").tail.concat.iterate(\k->[x:y|x<-['a'..'z'],y<-k])$[" "]
Olathe
źródło
0

Befunge (72)

<_v#:/*2+67\+++88*99%*2+76:
^ >$>:#,_84*+,1+:0\:" Lr$W~"67++**1+***6+`#@_

Prints strings 'a' to 'password' separated by spaces, then exits.

Below is a version that prints only the first 9*9 = 81 words ('a' to 'dd'), for comparison. The 99* is the number of iterations to perform.

<_v#:/*2+67\+++88*99%*2+76:
^ >$>:#,_84*+,1+:0\:99*`#@_
FireFly
źródło
0

JavaScript 80 76

for(i=s=0;s!="password";i++){s=i.toString(36).replace(/[0-9]/,'');console.log(s)}

fiddle - stops at "pa".

however this does repeat things.

Math chiller
źródło
You can initialize the loop with i=s=0 to save three more characters.
Ry-
@minitech done.
Math chiller
1
Why keep the var? i was a global before; now s is a global. You can just keep both globals in code golf, usually.
Ry-