PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zahlen Bruteforce



Leange
25.06.2009, 14:26
Hi

Ich möchte folgendes schreiben:

ein Programm das alle Kombinaten für die Ziffern von 0-9 bei 5 Stellen
(also 00000 bis 99999 ) durch geht aber nur die Kombinationen ausgibt die bestimmte Bedingungen erfüllen! (Der zweite Teil ist eigentlich kein Problem.)

Wie gehe ich das am besten an?

Ach so ... in C++ un ich bin (noch) nicht besonders gut darin! :o

MFG Leange

Ancient87
25.06.2009, 14:36
Das ganze hoert sich schwer nach Hausuebung an aber meh hier fast c++ pesudeo code, ich geb dir nicht die ganze loesung aber der rest sollte dir klar sein



for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
for(int k = 0; k < 10; k++)
{
/* den rest kannst dir denken (i hope)*/
/ * im letzten nestin level */
if(i == predicate && j == predicate && usw)
cout << i << j << k << //usw << endl;
}
}
}

Leange
25.06.2009, 14:43
Danke! Einwandfrei ^^

ähm ne inner Schule hab ich sowas leider noch nicht :(
aber es is ne Übungsaufgabe ja ^^

Danke noch mal
MFG Leange

DoS
25.06.2009, 14:50
float zahl;

for (i=0;i<=9;i++)
{
for (j=0;j<=9;j++)
{
for (k=0;k<=9;k++)
{
for (l=0;l<=9;l++)
{
for (m=0;m<=9;m++)
{

zahl = m && l && k && j && && i;
// Die Aufgaben mit der Zahl
}
}
}
}
}
Keine Ahnung, ob das funktioniert, ich bin selbst Anfänger.

Vor allen Dingen weiß ich gar nicht, ob es das && in dieser Nutzung gibt. Es soll so wie folgendes bei javascript wirken: Bei einer Zahl die in einem String steht. Wenn man solch zwei Zahlen (in einer variable) mit dem "+" addiert kommt z.B. bei : stringzahl1 + stringzahl2 (zahl1 ist 7 und zahl2 5) also 7 + 5= 75 . Dort dient das + als Verknüpfungsoperator.

So soll das && bei mir wirken.

Hoffentlich ihr habt es verstanden :D.

gruß

Edit: Lol, jetzt habe ich mal mein Gehirn angestrengt und dann war ein schneller ... Ancient hat das mit den && so gelöst indem er ein cout benutzt hat. Ich wollte es in eine Variable schreiben. Und ja ich saß anscheinend 15 Min. an meinem Post :D . Musste mir ja auch erst was überlegen :D

gruß

wacked
25.06.2009, 14:53
ähmm wiso so kompliziert:

int i;
while(i<10000){
i++;
if bedingungtesten(i)
cout<<i;
}

Ancient87
25.06.2009, 15:01
@wacked
weil er nehme ich an bestimmte attribute der Zahl checken will z.B die Zehnerstelle mindestens 2x so gross wie die 100er oder so. und das kannst du recht schwer wenn du das ganze als int machst (geht schon aber dann musst du anfangen mit bitmasking :D)

@DoS in c++ ist && ein logisches und & ist ein bitweises und. deine verknuepfung von && wird also in einem boolschen Wert (true oder false rauskommen) in deinem Falle true weil alles != 0 true ist. strin concatentation kannst du mit dem "+" operator machen.

Ausserdem warum willst du fuer eine ganzzahl einen float hernehmen ?

MFG

DoS
25.06.2009, 15:02
@wacked: Das geht nicht, weil bei z.B. 455 nur eben 455 angezeigt würden und nicht 00455. Und wenn du bruteforced kommt es auf jede Stelle an. Z.B. bei einem passwort, das "04" heißt. Ist zwar ein schlechtes Beispiel, aber da würde die Möglichkeit dann nicht zutreffen.

Berichtigt mich, wenn ich falsch liege. ;)

Zudem würde das schon beim Anfang (vielleicht) nicht funktionieren, weil du i nicht =0 gesetzt hast. =)

gruß

Edit: Verfickte scheiße. Du bist schon wieder schneller :D :D

@ancient: Weil ein normaler integer nur bis zu 5 Dezimal stellen speichern kann. Mit dem Float wollte ich nur sicher gehen, falls er ein bisschen erweitern möchte :) .

Also, wie bei JavaScript, hätte ich mir ja denken können . =)


gruß

blackberry
25.06.2009, 15:17
@wacked

Du musst i Initialisieren, da der Wert von i sonst undefiniert ist (nämlich der Wert, der vorher an dieser Speicherstelle war - was eigentlich alles sein kann)

Ancient87
25.06.2009, 15:22
ja dann verwendet man nen long :D

blackberry
25.06.2009, 15:53
@ancient: Weil ein normaler integer nur bis zu 5 Dezimal stellen speichern kann. Mit dem Float wollte ich nur sicher gehen, falls er ein bisschen erweitern möchte :) .

Ich heiße zwar nicht Ancient, aber das kann ich so nicht stehen lassen.
Du gehst scheinbar davon aus, dass ein Integer 16 Bit groß ist. Dies mag zwar für 16bit Betriebssysteme gelten, ist aber in der Zeit der 32bit (bzw. 64bit) Systeme nicht mehr gültig.

Starte doch mal folgendes Programm:

#include <stdio.h>


int main(int argc, char *argv[])
{
printf("Ein Integer ist %d Bit gross!\n", sizeof(int) * 8);
return 0;
}Ausgabe:
Ein Integer ist 32 Bit gross!
(dazu ist natürlich zu sagen, dass ich ein 32bit Betriebssystem benutze)

Ein "normaler" Integer ist folglich 32bit bzw. 64bit groß!

Mit einem solchen (signed) int kannst du maximal die Zahl 2,147,483,647 abbilden.
Das heißt: 9 Stellen genau und ein paar 10-stellige Zahlen.

@Threadstarter

Ich hab hier mal kurz eine "einfachere" Variante geschrieben.
Es wird einfach hochgezählt und die Ziffern werden einzeln extrahiert.
Dort wo das "TODO" steht, können Bedingungen eingefügt werden, z.B.:

if (hunderter != 5) continue;Also: nur Zahlen mit xx5xx ausgeben.

Hier der Code:


#include <stdio.h>

#define ZAHL_EXTRAHIEREN(name, nummer, var) \
name = var / nummer; \
var %= nummer;


int main(int argc, char *argv[])
{
int i;
int z;

int einer;
int zehner;
int hunderter;
int tausender;
int zehntausender;

for(i = 10000; i < 99999; i++)
{
z = i;

ZAHL_EXTRAHIEREN(zehntausender, 10000, z);
ZAHL_EXTRAHIEREN(tausender, 1000, z);
ZAHL_EXTRAHIEREN(hunderter, 100, z);
ZAHL_EXTRAHIEREN(zehner, 10, z);
ZAHL_EXTRAHIEREN(einer, 1, z);

// TODO: Bedingungen hier

printf(
"%d = %d%d%d%d%d\n",
i,
zehntausender, tausender,
hunderter, zehner, einer
);
}

return 0;
}

Ancient87
25.06.2009, 16:04
Ob das jetzt einfacher ist ist sicher so ne Frage Beeindruckender ist es allemal ;-) nur frage ich mich wirklich ob es sinnvoll ist einen Anfaenger mit dem preprocesor zu erschrecken. Desweiteren sollte jetzt von der komplexitaet 5 genestete auf 10 zaehlende wohl an eine auf 10000 rankommen nur sparst du dir die extrahiere calls.

Ich will hier auch wirklich nicht klugscheissen ich lerne selber grade c++ mich wuerd nur interessieren wieso du meinst deine Loesung sei einfacher. Imho ist die complexity gleich aber deine hat den overhead der extrahiere calls (x5) nur weis ich nicht wie das mit preprocessor funktionen aussieht nehmen an die sind effizienter als normale function calls ? Lasse mich gerne eines Besseren belehren.

MFG

blackberry
25.06.2009, 16:23
Darum habe ich "einfacher" auch in Anführungszeichen gestellt.
#define definiert Präprozessor-Makros.
Das heißt, dass vor dem Compilieren alle Makroaufrufe durch den Makrocode ersetzt werden.
Folglich entsteht auch kein Function-Overhead.

Persönlich finde ich das ganze übersichtlicher, da man nur einen Zähler benutzen muss.
Ob das ganze, wenn man die Extraktion der Zahlen verstehen will, immernoch einfacher erscheint bleibt sicher fraglich - ich finde es einfach nur schöner.

Zum Thema Performance:
Function-Overheads entstehen wie gesagt nicht.
Ob es besser ist 5 verschiedene Zählerschleifen laufen zu lassen, oder 10 Divisionen pro Runde (5x / + 5x %) auszuführen kann ich nicht sagen.
Sagen lässt sich nur, dass der Prozessor für Divisionen relativ viele Takte benötigt (bis zu 60 oder so - bin mir aber nicht sicher).
Andererseits übersetzt GCC eine Zählerschleife ungefähr so (nur das Inkrementieren, also den dritten Teil):

MOV eax, [ebp - X]
INC eax
MOV [ebp - X], eax
(X steht für eine Zahl, z.B. 4, oder 8)
Fünf von diesen Blöcken sind also sicher auch nicht sehr performant.
Wenn man dann auch noch mit den Zahlen rechnen will, muss man die echte Zahl bei den oberen Methoden erstmal generieren - was auch wieder einige Takte benötigt.

Anyway: bei so einem Programm kann einem die Performance mehr oder weniger eh egal sein - also wayne ;)


mfG. BlackBerry

Ancient87
25.06.2009, 16:36
Danke fuer die Klarstellung haeets mir fast selber denken sollen das direkt reinschreibt wobei wir da jetzt wieder bei dem alten Space vs Performance dilemma waeren.

Und klar ist die performance irreleveant aber ist trotzdem wie ich finde eine interessante Diskussion die zu allseitig besseren Verstaendnis der Materie sorgt. Aber ok bin jetzt rhuig ich bin halt durch 4 semester informatik studium schwerst geschaedigt :D

Danke nochmal fuer die Erklaerung

MFG

Leange
26.06.2009, 12:23
So danke habs mitlerweile un bastel jetzt nochn bissel rum! :D

@BlackBerry Was bedeutet das hier:

"%d = %d%d%d%d%d\n",
Diese d's ?

Sawyer
26.06.2009, 12:27
@leange
steht für double

MfG

blackberry
26.06.2009, 12:35
Nein.
%d steht für signed decimal integer.

DoS
26.06.2009, 12:51
Jetzt noch mal eine Lösung, die wirklich komplett ist. Damit ich meine nicht falsch da stehen lasse :D


float zahl;

for (i=0;i<=9;i++)
{
for (j=0;j<=9;j++)
{
for (k=0;k<=9;k++)
{
for (l=0;l<=9;l++)
{
for (m=0;m<=9;m++)
{

zahl = m + l + k + j + i;
// Die Aufgaben mit der Zahl
}
}
}
}
}
// Das ist nicht alles, da bisher nur 00400 usw. erfasst werden, also noch
//einmal ohne "0" damit "400" auch dabei ist

for (x=0; x<10000;x++)
{
zahl=x
//aufgaben mit zahl
}




gruß ;)

blackberry
26.06.2009, 13:03
Das kann nicht klappen!

zahl = m + l + k + j + i;
(btw: wieso float zahl - das ist total unnötig!)

Sagen wir mal wir sind bei 12345
Dann wäre:
zahl = 1 + 2 + 3 + 4 + 5;
Also:
zahl = 15;

Richtig wäre:
zahl = m * 10000 + l * 1000 + k * 100 + j * 10 + i;

PS: wozu ist der letzte Teil?
PS2: im letzten Teil fehlt ein Semikolon nach zahl=x


mfG. BlackBerry

DoS
26.06.2009, 16:59
Ich Dummkopf, du hast Recht.

sry , hatte den String vergessen. Aber deine Variante mit m*10000 usw. ist noch besser :)

Wie ich bereits sagte, bei einer Bruteforce z.B. von einem Passwort kann dieses so heißen: "41". Wenn man aber nur das so macht, wie ich es zuerst hingeschrieben hatte, wird nur "00041" abgefragt. Das heißt 41 wird nicht benutzt. Das habe ich versucht zu kompensieren mit meiner unteren Schleife.

Mir fällt auch gerade auf ,dass immer noch was fehlt: Nämlich z.B. 0441 . Weil ja nur 00441 und 441 durchgangen werden.

gruß

St3r3oboy
28.06.2009, 02:11
Das ganze hoert sich schwer nach Hausuebung an aber meh hier fast c++ pesudeo code, ich geb dir nicht die ganze loesung aber der rest sollte dir klar sein



for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
for(int k = 0; k < 10; k++)
{
/* den rest kannst dir denken (i hope)*/
/ * im letzten nestin level */
if(i == predicate && j == predicate && usw)
cout << i << j << k << //usw << endl;
}
}
}

ich hab mal ne frage an dich bzw an alle

wieso benutzt du referenzen? und wieso kommt es in codes so oft vor dass
zeiger mit so funktionsnamen benutzt werden während die funktionen selber nicht genutzt werden

hab ehrlich n riesen problem mit der notwendigkeit von zeigern und referenzen :confused::confused:

wacked
28.06.2009, 08:55
wen du zB einen array mit 1000 elemten hast und ihn sortieren willst und ihn einer funktion als zeiger übergibst hat das zwei vorteile:erstens ist es schneller und viel wichtiger:nach der funktion ist der array im hauptprog auch sortiert (->gültigkeitsbereiche).beispiel:

bool sortiereArray(int array){
//bubblesort hier einfügen
return ArraySortiert;}
beim verlassen der funktion hätte sich nix geändert. es gab nämlich 2 arays:eins in der main(oder von welcher funktion es aufgerufen wurde) und eins in der funktion sortiereArray. Das in der sortiereArray-funk ist sortiert aber sobald die funktion verlassen wird wird dieses array gelöscht.
void sortiereArray(int &Array){
//bubblesort
}
...
main()
...
sortiereArray(int *myArray);

DoS
28.06.2009, 10:01
Wie "wacked" bereits angesprochen hat:

Wenn du bei dem Thema Rückgabe von Funktionen schon warst , wirst du den Grund verstehen. Damit ist es nur möglich ein (1!) Wert zurückzugeben.

Das ist aber blöd, da du manchmal mehr als einen Wert von einer Variable verändern möchtest.

Dafür gibt es die sogenannten Zeiger und Referenzen. Es hat sich allerdings eingebürgert für solche Aufgaben, wie ich gerade geschildert habe, Pointer, also Zeiger zu verwenden. Die Zeiger erkennst du an dem "*" vor einer zunächst aussehenden Variable. Der Pointer macht nichts anderes, als die Adresse zu speichern und wenn dann der Pointer verändert wird, wird die Zieladresse auf die er zeigt, verändert.

Diese Zieladresse findest du mit einem "&" heraus. Bei der Initialisierung sieht das dann z.B. so aus:

int *Zeiger = &Variable;

Referenzen können zwar auch dazu benutzt werden, aber es hat sich eingebürgert, diese zu benutzen um Arbeit für den Rechner zu sparen. Das heißt, man benutzt sie, wenn man größere Werte einer Funktion übergeben will, sie allerdings nicht ändern möchte. Damit wird verhindert, dass eine 2. Kopie erstellt wird und spart somit Rechnenarbeit.

gruß :) P.S. Wenn du was nicht verstanden hast, dann frag lieber noch mal nach ;)

blackberry
28.06.2009, 11:50
Da das langsam nichts mehr mit dem Bruteforcen von Zahlen zutun hat:

/closed