Hackerboard Wiki HaboBlog
Hackerboard bei Facebook Hackerboard bei Google+ Hackerboard bei Twitter

[HaBo]

 
Programmieraufgaben Hier wird regelmäßig eine neue Programmieraufgabe gestellt, die dann gelöst werden soll und in Zusammenarbeit mit den Moderatoren auch besprochen werden kann.

Operatoren für gegebene Gleichung finden (Bruteforce)

Diskussion: Operatoren für gegebene Gleichung finden (Bruteforce) im Forum Programmieraufgaben, in der Kategorie Code Kitchen; Anzeige Folgende Programmieraufgabe wurde von IsNull eingereicht: Folgende Gleichung ist gegeben: (6_2)_8_9_1= 13 Die Underlines stellen einen Operator dar, welchen ...

Like Tree1Likes

Antwort
Alt 12.01.07, 18:46   #1 (permalink)
Member of Honour
 
Benutzerbild von ivegotmail
 
Registriert seit: 28.05.03
ivegotmail Leistung: Z3
Likes: 1
Standard Operatoren für gegebene Gleichung finden (Bruteforce)

Anzeige

Folgende Programmieraufgabe wurde von IsNull eingereicht:

Folgende Gleichung ist gegeben: (6_2)_8_9_1= 13
Die Underlines stellen einen Operator dar, welchen muss man herausfinden.

Ziel: Möglichst schneller Bruteforcer, der die Gleichung mit den richtigen Operatoren ausstattet.

__________________
http://livehabo.hackerboard.de | http://livebb.sourceforge.net
ivegotmail ist offline   Mit Zitat antworten
Alt 12.01.07, 19:23   #2 (permalink)
 
Registriert seit: 11.09.05
heinzelJacKy Leistung: Facit NTK
heinzelJacKy eine Nachricht über ICQ schicken heinzelJacKy eine Nachricht über AIM schicken
Likes: 0
Standard

welche operatoren sind denn genau zugelassen? also nur +-*/ oder auch %, ^ etc?
punkt vor strich sollte schätze ich mal auch eingehalten werden.. ist das wirklich noch schwierigkeit 1??

edit: k, habs jetz in javascript gemacht, da c++ keine mit Eval vergleichbare funktion besitzt ^^ dadurch wird natuerlich die forderung nach nem schnellen bruteforcer net erfuellt. evtl mach ich das ganze noch in c, wobei das bzgl. punkt vor strich wohl grauslig wird und schon fast nach ner math engine schreit..

Hier die Html-version   

<html>
<script>
//(6_2)_8_9_1= 13
ops = Array('+', '-', '*', '/', '%', '^');
op = Array();
document.write("<table>");
for (op[1] in ops) { //4 unbekannte
for (op[2] in ops) { //4 unbekannte
for (op[3] in ops) { //4 unbekannte
for (op[4] in ops) { //4 unbekannte
str = "(6"+ops[op[1]]+"2)"+ops[op[2]]+"8"+ops[op[3]]+"9"+ops[op[4]]+"1";
if(eval(str)==13) {
document.write("<tr><td>"+str+"</td><td> = </td><td>"+eval(str));
document.write(" <b style=\"color:red\">MATCH!</b></td></tr>")
}
else
document.write("</td></tr>");
}
}
}
}
</script>
</html>
heinzelJacKy ist offline   Mit Zitat antworten
   
HaBOT
 
- Anzeige -

Werbung ist gerade online    
Alt 12.01.07, 20:03   #3 (permalink)
 
Registriert seit: 01.11.03
lagalopex Leistung: Facit NTK
Likes: 0
Standard

Ist die Aufgabenstellung jetzt genau auf "(6_2)_8_9_1= 13" ausgelegt oder soll das eine beliebige dynamische Eingabe sein?
Welche Operatoren sind erlaubt (Priorität?). Division soll genau sein? (keine Integerdivision)
lagalopex ist offline   Mit Zitat antworten
Alt 13.01.07, 00:10   #4 (permalink)
 
Registriert seit: 07.07.04
M.D.Geist Leistung: Facit NTK
Likes: 0
Standard

Ich habe die Aufgabe mal mit C gelöst, als Operatoren habe ich nur + - * / zugalassen.

Bruteforcer   

Code:
#include <stdio.h>
void format(double * wert, int i, int j, int k, int l);
void ausgabe(char * gleichung, char * op, double erg, int i, int j, int k, int l);
int main(void) {
  char op[4]={'+','-','*','/'};
  int i,j,k,l;
  int f;
  double wert[5];
  wert[0]=6;
  double erg;
  char gleichung[15];
  gleichung[0]='(';
  gleichung[1]='6';
  gleichung[3]='2';
  gleichung[4]=')';
  gleichung[6]='8';
  gleichung[8]='9';
  gleichung[10]='1';
  gleichung[11]='=';
  gleichung[12]='1';
  gleichung[13]='3';
  gleichung[14]='\0';  
  for(i=0;i<4;i++) {
    for(j=0;j<4;j++) {
      for(k=0;k<4;k++) {
        for(l=0;l<4;l++) {
          if((i<2)&&(j<2)&&(k<2)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]+wert[2]+wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i<2)&&(j<2)&&(k<2)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]+wert[2]+wert[3]*wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }           
          }
          if((i<2)&&(j<2)&&(k>1)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]+wert[2]*wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i<2)&&(j<2)&&(k>1)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]+wert[2]*wert[3]*wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i<2)&&(j>1)&&(k<2)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]*wert[2]+wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i<2)&&(j>1)&&(k<2)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]*wert[2]+wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i<2)&&(j>1)&&(k>1)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]*wert[2]*wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i<2)&&(j>1)&&(k>1)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]+wert[1]*wert[2]*wert[3]*wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j<2)&&(k<2)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]+wert[2]+wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j<2)&&(k<2)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]+wert[2]+wert[3]*wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j<2)&&(k>1)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]+wert[2]*wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j<2)&&(k>1)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]+wert[2]*wert[3]*wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j>1)&&(k<2)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]*wert[2]+wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j>1)&&(k<2)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]*wert[2]+wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j>1)&&(k>1)&&(l<2)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]*wert[2]*wert[3]+wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
          if((i>1)&&(j>1)&&(k>1)&&(l>1)) {
            format(wert,i,j,k,l);
            erg=wert[0]*wert[1]*wert[2]*wert[3]*wert[4];
            if(erg==13) {
              ausgabe(gleichung,op,erg,i,j,k,l);
            }
          }
        }
      }
    }
  }
  system("PAUSE");
  return 0;
}

void format(double * wert, int i, int j, int k, int l) {
  switch(i) {
    case 0: wert[1]=2; break;
    case 1: wert[1]=(-2); break;
    case 2: wert[1]=2; break;
    case 3: wert[1]=(double)1/2; break;
  }
  switch(j) {
    case 0: wert[2]=8; break;
    case 1: wert[2]=(-8); break;
    case 2: wert[2]=8; break;
    case 3: wert[2]=(double)1/8; break;
  }
  switch(k) {
    case 0: wert[3]=9; break;
    case 1: wert[3]=(-9); break;
    case 2: wert[3]=9; break;
    case 3: wert[3]=(double)1/9; break;
  }
  switch(l) {
    case 0: wert[4]=1; break;
    case 1: wert[4]=(-1); break;
    case 2: wert[4]=1; break;
    case 3: wert[4]=1; break;
  }
}

void ausgabe(char * gleichung, char * op, double erg, int i, int j, int k, int l) {
  gleichung[2]=op[i];
  gleichung[5]=op[j];
  gleichung[7]=op[k];
  gleichung[9]=op[l];
  printf("%s\tErg: %lf\n",gleichung,erg);
}
M.D.Geist ist offline   Mit Zitat antworten
Alt 13.01.07, 11:45   #5 (permalink)
IsNull
Guest
 
Likes:
Standard

Zitat:
Ist die Aufgabenstellung jetzt genau auf "(6_2)_8_9_1= 13" ausgelegt oder soll das eine beliebige dynamische Eingabe sein?
Da sie jetzt schon gelöst ist, wäre es eine Herausforderung auch mit varierender Operatorzahl eine Lösung zu finden.

mfg
IsNull
  Mit Zitat antworten
Alt 13.01.07, 14:50   #6 (permalink)
 
Registriert seit: 01.11.03
lagalopex Leistung: Facit NTK
Likes: 0
Standard

So, meine kurze Lösung... 100 Zeilen, prüft beliebige "Gleichungen". Platzhalter _ sonst sind + - * / Klammern sowie Ziffern von 0-9 erlaubt. Es muss ein = vorkommen. (Syntax wird nicht geprüft.)
100 Zeilen C++   
Code:
#include <iostream>
#include <string>
#include <sstream>

using namespace std;


int stoi(string str)
{
	stringstream s(str);
	int a;
	s >> a;
	return a;
}

double opt(double w, char o, double x)
{
	switch (o) {
	case '+' : return w + x;
	case '-' : return w - x;
	case '*' : return w * x;
	case '/' : return w / x;
	default: cout << "Unknown tokken " << o << endl;
	};
	return 0.0;
}

double parsestr(string s);

bool parse(string s, double &r, char o)
{
	int i, b = 0, a = 0, f = 0;
	double w = 0.0;
	for (i = 0; i < s.length(); ++i) {
		if (s[i] == '(')
			++b;
		else if (s[i] == ')')
			--b;
		else if (s[i] == o && b == 0) {
			if (f)
				w = opt(w, o, parsestr(s.substr(a, i - a)));
			else
				w = parsestr(s.substr(a, i - a));
			f = 1;
			a = i + 1;
		}
	}
	if (f) {
		r = opt(w, o, parsestr(s.substr(a, i - a)));
		return true;
	}
	return false;
}

double parsestr(string s)
{
	double w = 0.0;
	if (parse(s, w, '+'))
		return w;
	if (parse(s, w, '-'))
		return w;
	if (parse(s, w, '*'))
		return w;
	if (parse(s, w, '/'))
		return w;
	if (s[0] == '(' && s[s.length()-1]==')')
		return parsestr(s.substr(1, s.length() - 2));

	return stoi(s);
}

void solve(string s)
{
	string::size_type p = s.find("_", 0);
	if (p == string::npos) {
		unsigned int p = s.find("=", 0);
		double w = parsestr(s.substr(0, p));
		double x = parsestr(s.substr(p + 1));
		if (w + 1e-12 > x && w - 1e-12 < x)
			cout << s << endl;
		return;
	}
	s[p] = '+';
	solve(s);
	s[p] = '-';
	solve(s);
	s[p] = '*';
	solve(s);
	s[p] = '/';
	solve(s);
}


int main()
{
	string test;
	cin >> test;
	solve(test);
	return 0;
}

Bei mir braucht der Code knapp 15ms für die beiden Lösungen der Beispielgleichung.
lagalopex ist offline   Mit Zitat antworten
Alt 22.03.08, 14:18   #7 (permalink)
 
Registriert seit: 22.03.08
MontyPerl Leistung: Facit NTK
Likes: 0
Standard

Mit denselben Funktionen, die ich auch hier benutzt habe, wandle ich den Term hier immer in postfix um und berechne das Ergebnis dann. Der Lösungsalgorithmus ist ein Backtracking Algorithmus (ich bin grade im Backtracking-Fieber). Das, zusammen mit dem ganzen von infix nach postfix Umgewandle resultiert in recht unperformantem code.
Zitat:
Bei mir braucht der Code knapp 15ms für die beiden Lösungen der Beispielgleichung.
Da kann ich drüber:
Code:
time ./equationBacktracker.pl '( 6 _ 2 ) _ 8 _ 9 _ 1 = 13'
( 6 * 2 ) - 8 + 9 * 1
( 6 * 2 ) - 8 + 9 / 1

real    0m2.183s
user    0m1.952s
sys     0m0.013s
Außerdem muss jeder Teil der Gleichung schön durch Leerzeichen von den anderen Teilen der Gleichung getrennt sein (aber in der Aufgabenstellung gehts ja auch nicht darum eine Gleichung möglichst allumfassend zu parsen..)
klick mich   
Code:
#!/usr/bin/env perl
use warnings;
use strict;


my $Operator = qr{[-+/%*x]};
my $Number = qr{[-+]?(:?(:?[1-9][0-9]*)?\.)?[1-9][0-9]*};
my $Bracket = qr{[)(]};


sub calcPostfix {
    my @numStack;
    foreach my $atom (@_) {
        if ($atom =~ m{^$Number$}) {push(@numStack, $atom)}
        elsif ($atom =~ m{^$Operator$}) {
            my ($b, $a) = (pop(@numStack), pop(@numStack));
            unless ($a) {$a = 0}
            unless ($b) {
                $b = 0;
                if ($atom =~ m{[/%]}) {return '1.23456789'} # Division by zero? nothx
            }
            my $result;
            if    ($atom eq '*' or $atom eq 'x'){$result = $a * $b}
            elsif ($atom eq '/' or $atom eq '%'){$result = $a / $b}
            elsif ($atom eq '+')                {$result = $a + $b}
            elsif ($atom eq '-')                {$result = $a - $b}
            push(@numStack, $result)
        }
    }
    return pop(@numStack)
}

sub infix2postfix {
    my (@postfixTerm, @opStack);
    # A precendence-hash mapping operators to integers representing their precendence.
    my %precHash = ('*'   =>   2,
                    'x'   =>   2,
                    '%'   =>   2,
                    '/'   =>   2,
                    '+'   =>   1,
                    '-'   =>   1,
                    ')'   =>   0,
                    '('   =>   0,
                    'EOT' =>   0);

    push(@opStack, "EOT");
    PARSE: foreach my $atom (@_, "EOT") {       # EOT == "End of term" mark
        if    ($atom =~ m{^$Number$}) {push(@postfixTerm, $atom)}
        elsif ($atom =~ m{^$Operator$}) {
            if ($precHash{$atom} > $precHash{$opStack[$#opStack]}) {push(@opStack, $atom)}
            else {
                push(@postfixTerm, pop(@opStack));
                redo PARSE
            }
        }
        elsif ($atom =~ m{^$Bracket$}) {
            if ($atom eq '(') {push(@opStack, $atom)}
            else {
                while($opStack[$#opStack] ne '(') {push(@postfixTerm, pop(@opStack))}
                pop(@opStack)
            }
        }
        elsif ($atom eq "EOT") {
            push(@postfixTerm, pop(@opStack)) until ($opStack[$#opStack] eq "EOT")
        }
    }
    return @postfixTerm
}

sub bruteforce {
    my ($solutions, $res, @data) = @_;
    foreach my $pos (@data) {
        if ($pos eq '_') {
            foreach my $op ('*', '/', '+', '-') {
            $pos = $op;
            if (bruteforce($solutions, $res, @data)) {return 1}
            }
            $pos = '_'
        }
    }
    if (calcPostfix(infix2postfix(@data)) == $res) {
        my $solString = join(' ', @data);
        if (($solString !~ /_/) and (not grep(($_ eq $solString), @$solutions))) {
            push(@$solutions, join(' ', @data));
            return 0
        }
    }
}

my @data;

if (@ARGV) {@data = split(/\s+/, $ARGV[0])}
else {print "\$-> "; my $inp = <>; chomp($inp); @data = split(/\s+/, $inp)}

my $result = pop(@data);
pop(@data);

my @solutions;
bruteforce(\@solutions, $result, @data);

foreach (@solutions) {print "$_\n"}

Der Term wird entweder von stdin oder vom *ersten* Argument gelesen. Außerdem sollte man auf Gleichungen mit "krummen" Ergebnissen absehen. (float Vergleiche mit == unzo, ihr wisst schon..)

?: hier mal das ganze mit eval, unsicherer, aber wesentlich schneller:
ich bin schneller   
Code:
#!/usr/bin/env perl
use warnings;
use strict;

sub bruteforce {
    my ($solutions, $res, @data) = @_;
    foreach my $pos (@data) {
        if ($pos eq '_') {
            foreach my $op ('*', '/', '+', '-') {
            $pos = $op;
            if (bruteforce($solutions, $res, @data)) {return 1}
            }
            $pos = '_'
        }
    }
    if (!grep $_ eq '_', @data) {
        my $solString = join(' ', @data);
        my $result = eval $solString;
        if ((defined $result) and ($result == $res) and (not grep(($_ eq $solString), @$solutions))) {
            push(@$solutions, join(' ', @data));
            return 0
        }
    }
}

my @data;

if (@ARGV) {@data = split(/\s+/, $ARGV[0])}
else {print "\$-> "; my $inp = <>; chomp($inp); @data = split(/\s+/, $inp)}

my $result = pop(@data);
pop(@data);

my @solutions;
bruteforce(\@solutions, $result, @data);

foreach (@solutions) {print "$_\n"}

Code:
time ./equationBacktrackerEval.pl '( 6 _ 2 ) _ 8 _ 9 _ 1 = 13'
( 6 * 2 ) - 8 + 9 * 1
( 6 * 2 ) - 8 + 9 / 1

real    0m0.661s
user    0m0.536s
sys     0m0.005s
??: aber "schnell" isses immernoch nicht:
Code:
time ./equationBacktrackerEval.pl '( 1 _ 2 ) _ 10 _ ( 4 _ ( 5 _ ( 2 _ 1 ) ) ) = -30'
( 1 / 2 ) * 10 * ( 4 - ( 5 * ( 2 * 1 ) ) )
( 1 / 2 ) * 10 * ( 4 - ( 5 * ( 2 / 1 ) ) )
( 1 + 2 ) * 10 * ( 4 - ( 5 * ( 2 - 1 ) ) )
( 1 + 2 ) * 10 * ( 4 - ( 5 / ( 2 - 1 ) ) )
( 1 + 2 ) * 10 / ( 4 - ( 5 * ( 2 - 1 ) ) )
( 1 + 2 ) * 10 / ( 4 - ( 5 / ( 2 - 1 ) ) )
( 1 + 2 ) * 10 - ( 4 * ( 5 * ( 2 + 1 ) ) )
( 1 - 2 ) * 10 - ( 4 * ( 5 * ( 2 - 1 ) ) )
( 1 - 2 ) * 10 - ( 4 * ( 5 / ( 2 - 1 ) ) )
( 1 - 2 ) - 10 - ( 4 + ( 5 * ( 2 + 1 ) ) )

real    7m51.761s
user    6m1.156s
sys     0m0.025s
Bwahahaha..
MontyPerl ist offline   Mit Zitat antworten
Alt 23.06.08, 18:43   #8 (permalink)
 
Registriert seit: 15.01.08
LionC Leistung: Facit NTK
Likes: 0
Standard

könnte man den für einen bruteforcer, der eine eingegebene gleichung rausfinden soll denn nicht einen codegenerator schreiben?
ist das überhaupt erlaubt?
LionC ist offline   Mit Zitat antworten
Alt 22.07.08, 21:11   #9 (permalink)
 
Registriert seit: 20.07.06
Darkslide Leistung: Facit NTK
Likes: 21
Standard

Meine Python Version:

Code:
from __future__ import division

def bruteforcer(gleichung="(6a2)b8c9d1=13", operatoren=["+", "-", "*", "/"]):
    for a in operatoren:
        for b in operatoren:
            for c in operatoren:
                for d in operatoren:
                    neue_gleichung=gleichung.replace("a", "%s"%a)
                    neue_gleichung2=neue_gleichung.replace("b", "%s"%b)
                    neue_gleichung3=neue_gleichung2.replace("c", "%s"%c)
                    neue_gleichung4=neue_gleichung3.replace("d", "%s"%d)
                    neue_gleichung5=neue_gleichung4.replace("=", "==")
                    if eval(neue_gleichung5):
                        print neue_gleichung4
Nicht die eleganteste Lösung aber immerhin sehr kurz...*zu Geists Variante schau*
Darkslide ist offline   Mit Zitat antworten
Alt 22.07.08, 22:49   #10 (permalink)
CDW
Moderator
 
Benutzerbild von CDW
 
Registriert seit: 20.07.05
CDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: Opteron
Likes: 202
Standard

prolog   

Code:
oper(Op1,Op2,Op1*Op2,*).
oper(Op1,Op2,Op1/Op2,/).
oper(Op1,Op2,Op1+Op2,+).
oper(Op1,Op2,Op1-Op2,-).

suche(Loesung):-  oper(6,2,Temp1,Op1), KlammerErgebnis is Temp1,
                  oper(KlammerErgebnis,8,Temp2,Op2),
                  oper(Temp2,9,Temp3,Op3),
                  oper(Temp3,1,Erg,Op4),
                  13 is Erg, %schöne ausgabe machen
                  concat_atom(['(',6,Op1,2,')',Op2,8,Op3,9,Op4,1,'=',13],Loesung).
Wer sich den Operator zwichen 6 und 2 denken kann:
Code:
oper(Op1,Op2,Op1*Op2).
oper(Op1,Op2,Op1/Op2).
oper(Op1,Op2,Op1+Op2).
oper(Op1,Op2,Op1-Op2).

suche(Loesung):-  oper(6,2,Temp1),Klammer is Temp1,
                  oper(Klammer,8,Temp2),
                  oper(Temp2,9,Temp3),
                  oper(Temp3,1,Loesung),
                  13 is Loesung.
__________________
Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf!
Selig, wer nichts zu sagen hat und trotzdem schweigt.
CDW ist offline   Mit Zitat antworten
Alt 03.01.09, 12:50   #11 (permalink)
 
Registriert seit: 26.12.08
Athelstan Leistung: Facit NTK
Athelstan eine Nachricht über ICQ schicken
Likes: 0
Standard

Hier meine Lösung in ruby:

Code:
a = ["+", "-", "*", "/"]; b = a; c = a; d = a; string_e = ""
a.each { |part1|
	b.each { |part2|
		c.each { |part3|
			d.each { |part4|
				string_e = "(6.0#{part1}2.0)#{part2}8.0#{part3}9.0#{part4}1.0"
				if eval(string_e).to_f == 13
					puts "Loesung gefunden: #{string_e}=13"; exit
				end
			}
		}
	}
}
Ausgabe:

Code:
athelstan@127.0.0.1:~$ ruby Operator.rb
Loesung gefunden: (6.0*2.0)-8.0+9.0*1.0=13
Lässt man das "exit" in Zeile 8 weg, kommt folgendes heraus, was logisch gesehen genau das gleiche ist:

Code:
athelstan@127.0.0.1:~$ ruby Operator.rb
Loesung gefunden: (6.0*2.0)-8.0+9.0*1.0=13
Loesung gefunden: (6.0*2.0)-8.0+9.0/1.0=13
9 geteilt durch 1 und mal 1 ergibt immer dasselbe, nämlich 9 - sonnenklar
Athelstan ist offline   Mit Zitat antworten
Alt 10.07.11, 15:31   #12 (permalink)
 
Benutzerbild von IGotMuscles
 
Registriert seit: 09.07.11
IGotMuscles Leistung: Facit NTK
Likes: 2
Standard hello

dashier ist ein ziemlich langer code für sowas,
aber das ist mein erster "brute force" und somit denk ich mal ganz passabel.

c++:

1   
Code:
#include <iostream>
#include <ctime>
#include <conio.h>
#include <string>
using namespace std;

// (6_2)_8_9_1= 13 - finde die Gleichung 

int rechnung = 0;
string kette;

int teste( int zeins, int zzwei, int zdrei, int zvier );

int main()
{
    int oeins = 0, ozwei = 0, odrei = 0, ovier = 0;
    srand(time(NULL));

    while( rechnung != 13)
    {
        rechnung = 0;
        kette = "";
        oeins = (rand() % 4);
        ozwei = (rand() % 4);
        odrei = (rand() % 4);
        ovier = (rand() % 4);
        teste ( oeins, ozwei, odrei, ovier );
    }

    if( rechnung == 13)
    {
        cout << "Ergebnis: " << kette << " = 13" << endl;
    }
    cout << "Druecken Sie eine beliebige Taste um das Fenster zu schliessen" << endl;
    getch();
    return 0;
}

int teste( int zeins, int zzwei, int zdrei, int zvier )
{    
    if( zeins == 0 )
    {
        rechnung += (6+2);
        kette += "(6+2)";
    }
    else if( zeins == 1 )
    {
        rechnung += (6-2);
        kette += "(6-2)";
    }
    else if( zeins == 2 )
    {
        rechnung += (6*2);
        kette += "(6*2)";
    }
    else if( zeins == 3 )
    {
        rechnung += (6/2);
        kette += "(6/2)";
    }

    if( zzwei == 0 )
    {
        rechnung = rechnung + 8;
        kette += " +8";
    }
    else if( zzwei == 1 )
    {
        rechnung = rechnung - 8;
        kette += " -8";
    }
    else if( zzwei == 2 )
    {
        rechnung = rechnung * 8;
        kette += " *8";
    }
    else if( zzwei == 3 )
    {
        rechnung = rechnung / 8;
        kette += " /8";
    }

    if( zdrei == 0 )
    {
        rechnung = rechnung + 9;
        kette += " +9";
    }
    else if( zdrei == 1 )
    {
        rechnung = rechnung - 9;
        kette += " -9";
    }
    else if( zdrei == 2 )
    {
        rechnung = rechnung * 9;
        kette += " *9";
    }
    else if( zdrei == 3 )
    {
        rechnung = rechnung / 9;
        kette += " /9";
    }

    if( zvier == 0 )
    {
        rechnung = rechnung + 1;
        kette += " +1";
    }
    else if( zvier == 1 )
    {
        rechnung = rechnung - 1;
        kette += " -1";
    }
    else if( zvier == 2 )
    {
        rechnung = rechnung * 1;
        kette += " *1";
    }
    else if( zvier == 3 )
    {
        rechnung = rechnung / 1;
        kette += " /1";
    }

    return ( zeins, zzwei, zdrei, zvier );
}


keine ahnung ob der jetzt schnell ist oder nicht...

Geändert von IGotMuscles (10.07.11 um 15:33 Uhr) Grund: unvollständige beschreibung
IGotMuscles ist offline   Mit Zitat antworten
Alt 10.07.11, 17:32   #13 (permalink)
 
Registriert seit: 13.05.07
Enterprize1 Leistung: Facit NTK
Likes: 0
Standard

Eine weitere Python Lösung für beliebige Gleichungen:
Code:
from __future__ import division
import sys,itertools,time
startTime=time.time()
gleichung=sys.argv[1].replace("_","%s").replace("=","==")
numUnders=sys.argv[1].count("_")
solutions=[]
for opList in itertools.product("+-*/",repeat=numUnders):
	try:
		if eval(gleichung%opList): 
			solutions.append(gleichung%opList)
	except ZeroDivisionError:
		continue
print "Loeseungen: "+str(len(solutions))
for solution in solutions:
	print "\t"+solution
timeTook=time.time()-startTime
print "Dauer: "+str(timeTook)+"s"
Beispiel:
Code:
C:\Code\Python\HaBo>python OpFinder.py "(6_2)_8_9_1=13"
Loeseungen: 2
        (6*2)-8+9*1==13
        (6*2)-8+9/1==13
Dauer: 0.00799989700317s
Enterprize1 ist offline   Mit Zitat antworten
Alt 10.07.11, 17:40   #14 (permalink)
CDW
Moderator
 
Benutzerbild von CDW
 
Registriert seit: 20.07.05
CDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: Opteron
Likes: 202
Standard

*nach langer Zeit den Thread rauskram*
12 Zeilen Python. Löst/Prüft beliebige Gleichungen. Die üblichen mathematischen Funktionen wie cos, sin, sqrt usw. sind verfügbar.
Wegen 'eval' sollte es nur lokal genutzt werden.
py   

Code:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division

import sys
import math
import itertools

ops = ['+', '-', '*', '/']
expr = sys.argv[1].replace('=', '==')

for op_combo in itertools.product(ops, repeat=expr.count('_')):
    mod_expr = expr
    for op in op_combo:
        mod_expr = mod_expr.replace('_', op, 1)
    
    if eval(mod_expr, {"__builtins__":None}, math.__dict__):
        print "solution:", mod_expr

Ausgabe:
Code:
>evaluator.py (6_2)_8_9_1=13
solution: (6*2)-8+9*1==13
solution: (6*2)-8+9/1==13
Code:
>evaluator.py 2_3_5_7_11_13=100
solution: 2+3+5+7*11+13==100
Code:
>evaluator.py 2_3_5_7_11_sqrt(25)=20
solution: 2*3+5-7+11+sqrt(25)==20
Edit: hm, die Überschneidung mit dem anderen Python Post ist aber schon fast wie ein Lottotreffer.
__________________
Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf!
Selig, wer nichts zu sagen hat und trotzdem schweigt.
CDW ist offline   Mit Zitat antworten
Alt 10.07.11, 18:14   #15 (permalink)
 
Benutzerbild von IGotMuscles
 
Registriert seit: 09.07.11
IGotMuscles Leistung: Facit NTK
Likes: 2
Standard

Zitat:
Zitat von CDW Beitrag anzeigen
*nach langer Zeit den Thread rauskram*
[/code]
sry, dachte es wäre okay
IGotMuscles ist offline   Mit Zitat antworten
Antwort
   
- Anzeige -

Werbung ist gerade online    

[HaBo] » Software Home » Code Kitchen » Programmieraufgaben » Operatoren für gegebene Gleichung finden (Bruteforce)
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
C++ Operatoren überladen Kenniej91 Code Kitchen 11 11.01.09 11:48
Gleichung [Matheaufgabe] Lui-G Science & Fiction 3 03.07.07 19:42
Gleichung auflösen Lesco Off topic-Zone 7 02.05.06 19:22
Ich kann alle im Netzwerk finden, mich kann man auch finden aber nicht zugreifen Strahl Network · LAN, WAN, Firewalls 11 21.07.05 16:52


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61