Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  82 6703
Da ble det nedlasting av devcpp og å sette meg litt inn i C++ igjen
Så jeg prøver meg, men om det blir så bra eller effektivt spørs vel.

TheGEEK: 5,78 forsøk i snitt? Det er jo omtrent det jeg har i vanlig mastermind, 4 felt og 6 farger. Denne her har jo 5 felt og 16 "farger"? Har du en synsk algoritme eller har jeg misforstått noe?
Sist endret av 10goto10; 25. august 2007 kl. 17:23.
Hvis det han sier stemmer så er hans algoritme bedre enn min.
Men jeg tror min kan forbedres litt, skal se på den senere.

10goto10: Svarene som er gitt tilbake gjelder for hvert spesifikke felt, når du gjetter f.eks.
A 4 2 0 0
og får
2 1 1 0 0
så vet du at det var A som var riktig, og at det er 4 og 2 som er på feil plass.
Sist endret av TanteSpiker; 25. august 2007 kl. 18:24.
Litt statistikk:

Hver test kjøres 1000 ganger.

Kode

Base    Digits  Avg
5       3       3.097000
5       4       3.243000
5       5       3.463000
5       6       3.799000
5       7       4.059000
5       8       4.300000
10      3       4.536000
10      4       4.507000
10      5       4.660000
10      6       4.995000
10      7       5.364000
10      8       5.818000
16      3       6.137000
16      4       5.799000
16      5       5.739000
16      6       5.982000
16      7       6.352000
16      8       6.710000
20      3       7.145000
20      4       6.617000
20      5       6.444000
20      6       6.554000
20      7       6.831000
20      8       7.195000
Hvis noen tviler så kan man undersøke koden selv:
kodekode: http://ninjarape.net/nff1/solve7.py

Og ja, denne koden (og algoritmen) er helt original, jeg har ikke tatt kode eller algoritmen fra noe sted bortsett fra min egen hjerne.

10goto10:
Som du ser så har ikke antall digits så _veldig_ mye å si, 4 er ganske konsistent(så lenge base er endel større enn digits) bedre enn 3, og forskjellen mellom 4 og 5 er svært liten. Dette kommer av at når man har flere digits så kan man raskere "eliminere" søkerommet, altså fjerne alle tall som _ikke_ er i svaret.
Sist endret av TheGEEK; 25. august 2007 kl. 20:33.
Jeg var nede i 7 forsøk ca, så har jeg 'optimisert' litt, så nå er jeg oppe i 8,4 .. Men det er fordi optimiseringen ikke er helt ferdig, og jeg håper den siste delen fikser det igjen sånn jeg kommer ned der du er, eller enda lenger. (Fikk en bug som gjorde at i noen tilfeller, så kaster den bort tall som den skulle ha brukt, en gang trengte den til og med 25 forsøk pga. denne feilen)

Ikke frykt at jeg stjeler algoritmen din, python skjønner jeg ingenting av.
Sist endret av TanteSpiker; 26. august 2007 kl. 00:57.
Ah, jeg kom akkurat på en ting, dette er ikke "ekte" mastermind. Der får man jo ikke vite hvilke felt du har rett. Bare at x felt har riktig verdi ("farge"), men ikke hvilke(t).

Her får man jo vite hvilke felt som er riktig. Stoor forskjell My bad som tenkte litt feil. Og litt mer forståelig resultatene til de andre her.

Men vidarlo spesifiserte jo oppgaven slik da.


Edit:

Har heller ikke sett på theGEEKs kode (+php er gresk for meg). Derimot kjørte jeg Grantax' signatur i devcpp

Edit: eh, eller python..
Sist endret av 10goto10; 26. august 2007 kl. 09:35.
Tror jeg sov litt i timen her.. beklager. Ser nå at Grantax faktisk påpekte regelforskjell fra vanlig mastermind 2 ganger allerede. Det forenkler jo kodingen. Samt vidarlo og theGEEK's endring om duplikate tall og tilbakemeldinger (post #35).

Passet bra at du ikke ville ha GUI forresten, blir sånn typisk skoleoppgave med (kjedelig) tekst-basert DOS-boks. Fikk aldri helt swung over grafikk og / eller C++. Men benyttet anledningen til å sette meg litt inn i ihvertfall C++ igjen. Og det har jeg gjort nå, så da var det på tide å begynne, hehe.

Det gjenstår egentlig endel, men er på ca 7.95 forsøk på 10000 runs nå. (viktig å få med at det er under 8 )

Edit: typo
Sist endret av 10goto10; 28. august 2007 kl. 13:30.
Dersom du vil ha motivasjon er det bare å sette en deadline, det er umulig å motivere meg uten.
Sitat av vidarlo
Ei runde kan ha duplikate tall ja. Det er tilfeldig trekt, uavhengig av resten av serien.

Og sjølvsagt kan folk skrive i python, glømte bare å skrive det opp på lista.

Og m0b har nok rett. Det er ingen formell konkuranse, bare ei oppgave eg har tenkt litt på, og er spent på å sjå resultatet. Tenkte å sjå gjennom resultatet om EI UKES TID og kåre "vinneren" i den som har best algoritme.
Vis hele sitatet...
.
Det klarte jeg visst og overse.
Har bare et problem i programmet mitt som fikk meg til å gi opp.
Men skal sette meg ned litt i dag/morgen og løse det.
Har ikke hatt så mye tid til overs de siste dagene, men skal prøve å få skrevet en versjon i morgen. Skal ihvertfall prøve å battle thegeek sin 5.78, selv om jeg ikke har peiling på hvor mange forsøk algoritmen jeg har i hode mitt vil bruke..
I demand moar kode!
Nå orker jeg ikke mer, og finner uansett ikke noen tweaks nå umiddelbart som gjør algoritmen min noe særlig bedre. Etter 1 mill simuleringer fikk jeg et snitt på 6.02734 antall forsøk, som jeg er rimelig fornøyd med selv om theGeekMeister slår den greit

Kode: http://wasdstudios.dyndns.org/nff/ma...d/Master5.java
"Binary": http://wasdstudios.dyndns.org/nff/ma...d/Master.class

Kanskje jeg skal gå igjennom koden din og se om jeg finner noen bra tweaks geek, men legger ut med mine egne tweaks for nå ihvertfall.
Tja, her er nå mitt lille bidrag.

Bare rotet til rutinene som skulle låne vekk plassen til tall som var funnet for å eliminere søkerommet raskere (doblet antall forsøk plutslig istedenfor å få færre forsøk...), så denne er uten en slik metode. (Skjønner ikke hva jeg gjør feil der. Tar kanskje å ser mer på det)

Kun kjørt den 2 ganger 1000 runs, fikk 6.813 og 6.83 forsøk i snitt.

Kun brukt devcpp. Og ja, helt originalt (c) 10goto10 (Vel, med unntak av random-koden sikkert ikke helt standart C++ konvensjoner på variabler osv heller, og garanterer ikke for bugfriheten)

Vet ikke helt hvor jeg skal poste koden, så tar det i en rute her:

Kode

/* KEYFINDER

Sort of MasterMind-like

To guess the combination of a key of <DIGIT> nr. of digits of base <BASE>

author: 10goto10 @ nFF
dates: 2007.08.28 - 2007.08.30

  v0.07 - simple elimination method works
  v0.09 - refined elimination method a bit
  v0.18 - refined guess-selection method considerably (I think.. but at a big time-penalty...)
  v0.19 - small esthetic touch-up.
*/


#include <iostream>
#include <time.h>

using namespace std;


const int GAMERUNS = 1;  // nr. of games to run to calculate average from

const int OUTPUT = 1;  // 1 = Outputs guesses for each game. 0 = no output (for averaging lots of games..)
const int DEBUGINFO = 0;  // 1 = additional info.. beware info is one step behind

const int DIGITS = 5;  // nr. of digits to guess
const int BASE = 16;   // nr. of possibilities pr digit
const int MAXGUESSES = 20;  // insurance...


void resetgame(int& guesses, int& dcount, int borrowed[], int result[], int dmark[], int dfound[], int remposs[], int poss[][BASE]);
void think(int guesses, int& dcount, int& borrows, int borrowed[], int dfound[], int dmark[], int guesskey[], int result[], int remposs[], int poss[][BASE]);
void makeaguess(int guesses, int dcount, int dfound[],int dmark[], int guesskey[], int remposs[], int poss[][BASE]);
int feedback(int guesskey[], int key[], int result[]);
int foundcount(int dmark[]);

char uberhex(int tall);

int main()
{
  int guesses;
  int totguesses;
  int games; // games played
  int gresult;
  float average;
  int key[DIGITS+1];  // gidder ikke knote med element null
  int guesskey[DIGITS+1];
  int result[DIGITS+1]; // guess result
  int dfound[DIGITS+1]; // found digits
  int dcount; // number of found digits
  int borrows; // nr of borrows
  int dmark[DIGITS+1]; // which digits are found? 0 = not this 1 = this (sort of boolean)
  
  int poss[DIGITS+1][BASE] ; // possibilities-array. BASE start at 0...
  int remposs[DIGITS+1]; // number of remaining possibilites for a digit
  int borrowed[DIGITS+1]; // borrowed position to minimize guesses (boolean-ish)


  games = 0;
  totguesses = 0;
  average = 0.0;

  cout << "KEYFINDER 0.18. \n\n Games to run: " << GAMERUNS << ". Digits to find: " << DIGITS << ". Base: " << BASE << "\n";

  // randomize random seed
  time_t seconds;
  time(&seconds);
  srand((unsigned int) seconds);
  // cout << "random seed: " << seconds << endl;
  
  do
  {
    resetgame(guesses, dcount, borrowed, result, dmark, dfound, remposs, poss);
    // make a random key
    for(int i=1;i<DIGITS+1;i++)key[i] = rand()%BASE;

    if(OUTPUT==1)
    {
      cout << "\nKEY:    ";
      for(int i=1;i<=DIGITS;i++) // write the key
      { 
        if(i!=1)cout << " ";
        cout << uberhex(key[i]);
      }
      cout << endl << "=================" << endl;
      cout << "Guesses:" << endl;
    }

    do
    {
      think(guesses,dcount,borrows,borrowed,dfound,dmark,guesskey,result,remposs,poss);
      makeaguess(guesses,dcount,dfound,dmark,guesskey,remposs,poss);
      guesses += 1;
      gresult = feedback(guesskey,key,result);

      // Output stuff (how to make spaghetti without GOTO :-)
      if(DEBUGINFO==1)
      {
        // output borrow flags
        cout << " Borrow ";
        for(int i=1;i<=DIGITS;i++)
        {
          cout << borrowed[i];
          cout<<" ";
        }
      }
      if(OUTPUT==1)
      {
        cout << endl;
        // output guesses
        cout << " Nr." << guesses << " : ";
        for(int i=1;i<=DIGITS;i++)
        {
          //if(dmark[i]) cout << uberhex(dfound[i]); else cout << uberhex(guesskey[i]);
          cout << uberhex(guesskey[i]);
          cout<<" ";
        }
      }
      if(DEBUGINFO==1)
      {
        cout << " - found:" << foundcount(dfound);
      }
      if(DEBUGINFO==1)
      {
        cout << "\nRES " << guesses << " : ";
        for(int i=1;i<=DIGITS;i++)cout << result[i] << " ";
        cout << "\n";
      }
      if(DEBUGINFO==1)
      {
        cout << " space: ";
        for(int i=1;i<=DIGITS;i++)cout << uberhex(remposs[i]) << " ";
        cout << "\n\n";
      }
    } while(!gresult and guesses<MAXGUESSES);

    if(OUTPUT==1)cout << "\n\nGuesses: " << guesses << "\n\n";
    
    totguesses += guesses;
    games += 1;
    if(OUTPUT==0 and DEBUGINFO==0)cout << "."; // original progressbar
  } while(games<GAMERUNS);

  average = totguesses / (float)games;
  cout << "\n\n Finished. Games run: " << games << "\n  Average solve-steps(guesses): " << average << "\n";


  
  //cin.ignore();
  cin.get();
  return 1;
}



// Reset for new gamerun...
void resetgame(int& guesses, int& dcount, int borrowed[], int result[], int dmark[], int dfound[], int remposs[], int poss[][BASE])
{
     guesses = 0;
     dcount = 0;
     for(int d=1;d<=DIGITS;d++)
     {
             for(int b=0;b<BASE;b++)poss[d][b]=b;
             dfound[d]=0;
             dmark[d]=0;
             remposs[d]=BASE;
             result[d]=0;
             borrowed[d]=0;
     }
}


// Get current guess result. 1 = found key.
// result[digit]
//   0 = value dosn't exist anywere
//   1 = correct value at wrong position(digit)
//   2 = correct value at correct position
int feedback(int guesskey[], int key[], int result[])
{
  int res = 1;
  for(int k=1;k<=DIGITS;k++)result[k]=0;
  for(int g=1;g<=DIGITS;g++)
  {
    for(int k=1;k<=DIGITS;k++)
    {
      if(key[k]==guesskey[g])
      {
        if(k==g)result[g]=2;else if(result[g]!=2)result[g]=1;
      }
    }
  }
  for(int i=1;i<=DIGITS;i++)
  {
    if(result[i]!=2)res=0;
  }
  return res;
}


// make hex characters, 0-9  A-F or higher..
char uberhex(int tall)
{
  char dig;
  if(tall<10) dig=(char)(tall+48) ; else dig = (char)(tall+55);
  return dig;
}



void think(int guesses, int& dcount,int& borrows, int borrowed[], int dfound[], int dmark[], int guesskey[], int result[], int remposs[], int poss[][BASE])
{
  // Evaluate possible solutions left
  if(guesses>0)
  {
    for(int r=1;r<=DIGITS;r++)
    {
      if(borrowed[r]==0)
      {
        if(result[r]==2)
        {
          dcount += 1;
          dfound[r] = guesskey[r];
          dmark[r] = 1; // mark as found
          remposs[r] = 1; // the only possibility left
          poss[r][0] = guesskey[r]; // save value
        }
        if(result[r]==1) // remove from this position(digit)
        {
          int f=0;
          for(int i=0;i<remposs[r];i++)
          {
            if(guesskey[r]==poss[r][i])
            {
              for(int rem=i;rem<remposs[r];rem++)
              {
                poss[r][rem] = poss[r][rem+1];
              }
              remposs[r] -= 1;
              if(remposs[r]<1)remposs[r]=1; // just in case
              f=1;
            }
            if(f==1)break;
          }
        }
      }

      if(result[r]==0) // remove from all positions
      {
        for(int d=1;d<=DIGITS;d++)
        {
          for(int b=0;b<remposs[d];b++)
          {
            if(poss[d][b]==guesskey[r])
            {
              for(int rem=b;rem<remposs[d];rem++)
              {
                poss[d][rem]=poss[d][rem+1];
              }
              remposs[d] -= 1;
              if(remposs[d]<0)remposs[d]=0; // again;just in case
            }
          }
        }
      }
    }
  }


}



// the guessing game
void makeaguess(int guesses, int dcount, int dfound[], int dmark[], int guesskey[], int remposs[], int poss[][BASE])
{
  int step;
  int biggest=0;
  int comb[DIGITS+1];  // saved path with most different combination
  int scan[DIGITS+1];  // current tested path


  // if found all...
  if(foundcount(dmark)>=DIGITS)
  {
    for(int i=1;i<=DIGITS;i++)
    {
      guesskey[i] = dfound[i];
    }
 }
 else // Guess a new code
 {

    // Find the combination with the most nr of differences
    // The uber-supah scan-algorithm
    biggest = 0;
    int temp;
    for(int i=1;i<=DIGITS;i++)scan[i]=0;
    int ende;
    do
    {
      temp=0;
      for(int a=1;a<DIGITS;a++)
      {
        for(int b=a+1;b<=DIGITS;b++)
        {
          if(abs(poss[a][scan[a]]-poss[b][scan[b]])>0)temp++;
        }
      }
      if(temp>biggest)
      {
        biggest=temp;
        for(int s=1;s<=DIGITS;s++)
        {
          comb[s]=scan[s]; // save path
        }
      }
      scan[DIGITS]++; //increment last pointer
      for(int s=DIGITS-1;s>0;s--)
      {
        if(scan[s+1]>=remposs[s+1])scan[s]++;
      }
      ende=1;
      for(int s=1;s<=DIGITS;s++)
      {
        if(scan[s]<remposs[s])ende=0;
        if(scan[s]>=remposs[s])scan[s]=0;
      }
    }while(!ende);
    // the new guess
    for(int s=1;s<=DIGITS;s++)guesskey[s]=poss[s][comb[s]];

  }
    
}


int foundcount(int dmark[])
{
    int jall = 0;
    for(int i=1;i<=DIGITS;i++)
    {
      if(dmark[i])jall++;
    }
    return jall;
}

Edit: What, innrykkene i koden forsvant!
Sist endret av 10goto10; 30. august 2007 kl. 17:11.
Typisk nok fant jeg ut hvordan jeg kunne effektivisere koden en god del, etter å ha postet den. Så nå kunne jeg kjøre 10000 runs istedenfor (for utålmodig ellers).

Ligger nok litt høyere enn jeg sa i stad, rundt ca. 6.9 forsøk.. uten at det egentlig er så viktig hehe. Koden er nesten lik så poster ikke den en gang til, med mindre noen er veldig interessert.
Hehe, jeg er litt imponert over at du gidder skrive slikt i c:P
Så da er du imponert over noe i det minste? Hehe.

Men hvordan det egentlig, mer effektivt eller enklere i Python?
Begynte med java for noen dager siden, og tenkte jeg kunne prøve å lage denne oppgaven. Ble litt vanskeligere enn jeg hadde forestillt meg. Ihvertfall å få til en brukendes algoritme. Kildekoden ser ut som en oppspist ark med krysseduller.. Nesten :P

Holder på å feilsøker nå. Den klarer avanserte på 6-7 treff, mens enkle feiler den på :P

EDIT:

Aah, nice. Bug funnet. Da er det bare å kjøre den noen ganger å finne ut snittet
Sist endret av Dinithion; 30. august 2007 kl. 23:32.
Jeg har nok jukset litt, for koden håndterer foreløpig ikke duplikate tall, er nå nede i 5.4 på 10.000 runs. Regner med den går fin-fint opp når/om jeg modder den til å håndtere duplikater. Tviler ikke på den spretter opp til mellom 6 og 7.

Kom nettop på en veldig god ting jeg kunne gjøre for å optimisere, føler meg så dum for å ikke ha kommet på det før.
Jeg får vel begynne på nytt.
Laster opp i morgen regner jeg med.
Sist endret av TanteSpiker; 31. august 2007 kl. 13:17.
10goto10: python er mye mindre effektiv, men også ekstremt mye enklere å kode.
For slike ting som dette, altså hvor ytelsen ikke akkurat er så ekstremt farlig så er python genialt though.
Ok.
Regna vel med at C++ er ganske effektivt når det er kompilert, om enn mer tungvinn å kode. Men akkurat denne oppgaven krever jo ikke spesiellt annet enn litt tabell-triksing og "cout" (hehe), så er vel ikke så mye mer tungvin enn de fleste andre språk sånn sett.

Dessuten trengte jeg litt pause fra Half Life 2 (episode 1)

Har aldri vært borti Python, men har såvidt hørt om det.
Sikkerhetsklarert
Dinithion, har lest igjennom koden din.
Jeg har drevet så smått med c++, og tenkte jeg skulle prøve meg på denne oppgaven, men etter å ha sett koden din mistet jeg litt motet. Lyst til å legge ut en versjon med litt mer detaljerte kommentarer? Jeg klarer ikke helt å se hvor du gjør selve sammenligningen med guesset og key.
Og så vidt jeg ser så outputter den ikke 1,2 og 0?
Jeg har ikke lagt ut koden, så det er nok ikke min kode du ser på
Alle dere som koder i {språk som er stress å kode i}, prøv python (eller perl/ruby);P
Til lekekoding så er det imho ufattelig stress å bruke et språk med "sterke typer" (strongly typed).
Er også kjekt å kunne slippe ting som kompilering, minneallokering osv..
Sist endret av TheGEEK; 31. august 2007 kl. 23:40.
Jeg koder for å lære, og da er jeg ikke interresert i å ta noen snarveier. Ikke at java er stress. Men på den andre siden så kunne det være verdt å lære seg pyton/perl. Jeg likte dog denne oppgaven, og kommer sikkert til å prøve å lage tilsvarende i flere språk etterhvert.
Sitat av Pjukern
Dinithion, har lest igjennom koden din.
Jeg har drevet så smått med c++, og tenkte jeg skulle prøve meg på denne oppgaven, men etter å ha sett koden din mistet jeg litt motet. Lyst til å legge ut en versjon med litt mer detaljerte kommentarer? Jeg klarer ikke helt å se hvor du gjør selve sammenligningen med guesset og key.
Og så vidt jeg ser så outputter den ikke 1,2 og 0?
Vis hele sitatet...
Vet ikke om jeg skal føle meg truffet, siden du nevner C++?

Uansett, koden som sammenligner guesset og key er funksjonen "feedback".
Sikkerhetsklarert
Sitat av 10goto10
Vet ikke om jeg skal føle meg truffet, siden du nevner C++?

Uansett, koden som sammenligner guesset og key er funksjonen "feedback".
Vis hele sitatet...
Jeg mener selvsagt deg 10goto10

Men jeg ser ikke noe 1,2 og 0 ut til skjermen (cout), er det noe som bare returneres til programmet?

forklar meg gjerne hvordan du optimaliserte det.. bruker ca 2minutter på 1000runs nå.
Pjukern:

Ok, skal prøve. Men husk på at jeg ikke er noen C++ guru selv da. Har knotet med det litt for noen år siden riktignok, men ikke så mye. Og så nå da, selvsagt. Tenkte det var en god anledning til å prøve seg litt igjen.


En annen ting er at du må ikke bli overveldet av en annens kode Ser alltid forvirrende ut spør du meg, og så klarte jo code-boksen i forumet her å fjerne alle innrykkene da... ser jo mer spaghetti ut enn spaghetti!


Ang. outputs:
Hvis du setter konstanten DEBUGINFO til 1 (ca øverst i progget), så ser du noen ekstra linjer med info som spyttes ut, bl.a. resultat av "guesset", på linja "RES=". Aller øverst, per. gjetning/guess, er det en låne-tabell som ikke brukes i denne versjonen.. så kommer selve guesset, deretter RES, og så en tabell som inneholder antall løsninger som er igjen for akkurat den plassen/tallet (space-linja). Skrevet i, eh, "uberhex", hehe. dvs, F=15 som vanlig, og så videre, G=16, H =17... (dog vil det aldri bli 17.. er kun 16 til å begynne med med base=16).

(Noe av infoen er et trinn på etterskudd btw.. dvs det helt til høyre om antall funnede tall.. vet hvorfor, fikser det kanskje senere)

Det er ca linje 128 i koden ovenfor (som skriver ut resultatene) hvis du limer inn i en editor (Testet det nå og så at innrykkene kom med igjen, de vises visst tydeligvis ikke her i forumet).


Konstanten OUTPUT skriver ut hvert forsøk på alle spill. og konstanten GAMERUNS bestemmer da hvor mange spill som kjøres. Lønner seg å ha OUTPUT=0 for å teste f.eks. mange runs. Da skrives bare gjennomsnitlig antall forsøk etterpå.


Gjort sånn for enkelhets skyld, men kunne sikkert brukt argv også.



Effektiviseringen jeg snakket om gjaldt bare rutinen helt til slutt ( i "makeaguess"-funskjonen), dvs den som plukker ut nye tall å gjette på. Den plukker ut mest mulig forskjellige tall, og jeg testet da alle mulige kombinasjoner... fant bare ut at jeg kunne stoppe etter å ha funnet flest mulig forskjellige (åltså 5 forskjellige)... hehe. Akkurat det var ganske enkelt egentlig. Men slet litt med den algoritmen ellers..


Litt angående FEEDBACK-funksjonen:

Kode

// Get current guess result. 1 = found key.
// result[digit]
//   0 = value dosn't exist anywere
//   1 = correct value at wrong position(digit)
//   2 = correct value at correct position
int feedback(int guesskey[], int key[], int result[])
{
  int res = 1;
  for(int k=1;k<=DIGITS;k++)result[k]=0;  // resetter RESULT-tabellen til 0 for alle elementer


// Løkker for å teste hva RESULTatet ble:

  for(int g=1;g<=DIGITS;g++)
  {
    for(int k=1;k<=DIGITS;k++)
    {
      if(key[k]==guesskey[g])
      {
        if(k==g)result[g]=2;else if(result[g]!=2)result[g]=1; HER gis resultatet for et siffer
      }
    }
  }
  for(int i=1;i<=DIGITS;i++)
  {
    if(result[i]!=2)res=0;
  }
  return res;
}
Det er åltså setningen:

if(k==g)result[g]=2;else if(result[g]!=2)result[g]=1;

som er kjernen her.
guesskey[] er en tabell, fra guesskey[1] til [5] (egentlig fra 0, men bruker ikke den).
Det samme med result[] og key[], selvsagt.

Vet ikke hva jeg trenger å forklare, men:
Hvis et siffer(digit) programmet gjettet på er det samme på samme posisjon (k==g), så blir resultatet 2, hvis det er likt siffer men forskjellig posisjon, så blir resulatet 1, dersom det ikke er 2 fra før (else if(result[g]!=2)result[g]=1)



Ny kode:
(Obs, tok med "borrow"-delen, men den er kommentert ut da den ikke virker...)

Endret litt på koden nå, så nå kommer både resultat og guess ved at OUTPUT-konstanten =1, og det andre med DEBUGINFO-konstanten..

Kode

/* KEYFINDER

Sort of MasterMind-like

To guess the combination of a key of <DIGIT> nr. of digits of base <BASE>

author: 10goto10 @ nFF
dates: 2007.08.28 - 2007.08.31

  v0.07 - simple elimination method works
  v0.09 - refined elimination method a bit
  v0.18 - refined guess-selection method considerably (I think.. but at a big time-penalty...)
  v0.19 - small esthetic touch-up.
  v0.20 - Made the guess-selection more effective!
*/


#include <iostream>
#include <time.h>

using namespace std;


const int GAMERUNS = 1;  // nr. of games to run to calculate average from

const int OUTPUT = 1;  // 1 = Outputs guesses for each game. 0 = no output (for averaging lots of games..)
const int DEBUGINFO = 0;  // 1 = additional info.. beware info is one step behind

const int DIGITS = 5;  // nr. of digits to guess
const int BASE = 16;   // nr. of possibilities pr digit
const int MAXGUESSES = 20;  // insurance...


void resetgame(int& guesses, int& dcount, int borrowed[], int result[], int dmark[], int dfound[], int remposs[], int poss[][BASE]);
void think(int guesses, int& dcount, int& borrows, int borrowed[], int dfound[], int dmark[], int guesskey[], int result[], int remposs[], int poss[][BASE]);
void makeaguess(int guesses, int dcount, int mostdiffs, int dfound[],int dmark[], int guesskey[], int result[], int remposs[], int poss[][BASE]);
int feedback(int guesskey[], int key[], int result[]);
int foundcount(int dmark[]);

char uberhex(int tall);

int main()
{
  int guesses;
  int totguesses;
  int games; // games played
  int gresult;
  float average;
  int key[DIGITS+1];  // gidder ikke knote med element null
  int guesskey[DIGITS+1];
  int result[DIGITS+1]; // guess result
  int dfound[DIGITS+1]; // found digits
  int dcount; // number of found digits
  int borrows; // nr of borrows
  int dmark[DIGITS+1]; // which digits are found? 0 = not this 1 = this (sort of boolean)
  
  int poss[DIGITS+1][BASE] ; // possibilities-array. BASE start at 0...
  int remposs[DIGITS+1]; // number of remaining possibilites for a digit
  int borrowed[DIGITS+1]; // borrowed position to minimize guesses (boolean-ish)
  int mostdiffs;


  games = 0;
  totguesses = 0;
  average = 0.0;

  cout << "KEYFINDER 0.20. \n\n Games to run: " << GAMERUNS << ". Digits to find: " << DIGITS << ". Base: " << BASE << "\n";

  // randomize random seed
  time_t seconds;
  time(&seconds);
  srand((unsigned int) seconds);
  // cout << "random seed: " << seconds << endl;

  mostdiffs=0;
  for(int i=1;i<DIGITS;i++)mostdiffs+=i;

  
  do
  {
    resetgame(guesses, dcount, borrowed, result, dmark, dfound, remposs, poss);
    // make a random key
    for(int i=1;i<=DIGITS;i++)key[i] = rand()%BASE;

    if(OUTPUT==1)
    {
      cout << "\nKEY:    ";
      for(int i=1;i<=DIGITS;i++) // write the key
      { 
        if(i!=1)cout << " ";
        cout << uberhex(key[i]);
      }
      cout << endl << "=================" << endl;
      cout << "Guesses:" << endl;
    }

    do
    {
      think(guesses,dcount,borrows,borrowed,dfound,dmark,guesskey,result,remposs,poss);
      makeaguess(guesses,dcount,mostdiffs,dfound,dmark,guesskey,result,remposs,poss);
      guesses += 1;
      gresult = feedback(guesskey,key,result);

      // Output stuff (how to make spaghetti without GOTO :-)
      if(DEBUGINFO==1)
      {
        // output borrow flags
        cout << " Borrow ";
        for(int i=1;i<=DIGITS;i++)
        {
          cout << borrowed[i];
          cout<<" ";
        }
      }
      if(OUTPUT==1)
      {
        cout << endl;
        // output guesses
        cout << " Nr." << guesses << " : ";
        for(int i=1;i<=DIGITS;i++)
        {
          //if(dmark[i]) cout << uberhex(dfound[i]); else cout << uberhex(guesskey[i]);
          cout << uberhex(guesskey[i]);
          cout<<" ";
        }
      }
      if(DEBUGINFO==1)
      {
        cout << " - found:" << foundcount(dfound);
      }
      if(OUTPUT==1)
      {
        cout << "\nRES " << guesses << " : ";
        for(int i=1;i<=DIGITS;i++)cout << result[i] << " ";
        cout << "\n";
      }
      if(DEBUGINFO==1)
      {
        cout << " space: ";
        for(int i=1;i<=DIGITS;i++)cout << uberhex(remposs[i]) << " ";
        cout << "\n\n";
      }
    } while(!gresult and guesses<MAXGUESSES);

    if(OUTPUT==1)cout << "\n\nGuesses: " << guesses << "\n\n";
    
    totguesses += guesses;
    games += 1;
    if(OUTPUT==0 and DEBUGINFO==0)cout << "."; // original progressbar
  } while(games<GAMERUNS);

  average = totguesses / (float)games;
  cout << "\n\n Finished. Games run: " << games << "\n  Average solve-steps(guesses): " << average << "\n";


  
  //cin.ignore();
  cin.get();
  return 1;
}



// Reset for new gamerun...
void resetgame(int& guesses, int& dcount, int borrowed[], int result[], int dmark[], int dfound[], int remposs[], int poss[][BASE])
{
     guesses = 0;
     dcount = 0;
     for(int d=1;d<=DIGITS;d++)
     {
             for(int b=0;b<BASE;b++)poss[d][b]=b;
             dfound[d]=0;
             dmark[d]=0;
             remposs[d]=BASE;
             result[d]=0;
             borrowed[d]=0;
     }
}


// Get current guess result. 1 = found key.
// result[digit]
//   0 = value dosn't exist anywere
//   1 = correct value at wrong position(digit)
//   2 = correct value at correct position
int feedback(int guesskey[], int key[], int result[])
{
  int res = 1;
  for(int k=1;k<=DIGITS;k++)result[k]=0;
  for(int g=1;g<=DIGITS;g++)
  {
    for(int k=1;k<=DIGITS;k++)
    {
      if(key[k]==guesskey[g])
      {
        if(k==g)result[g]=2;else if(result[g]!=2)result[g]=1;
      }
    }
  }
  for(int i=1;i<=DIGITS;i++)
  {
    if(result[i]!=2)res=0;
  }
  return res;
}


// make hex characters, 0-9  A-F or higher..
char uberhex(int tall)
{
  char dig;
  if(tall<10) dig=(char)(tall+48) ; else dig = (char)(tall+55);
  return dig;
}



void think(int guesses, int& dcount,int& borrows, int borrowed[], int dfound[], int dmark[], int guesskey[], int result[], int remposs[], int poss[][BASE])
{
  // Evaluate possible solutions left
  if(guesses>0)
  {
    for(int r=1;r<=DIGITS;r++)
    {
      if(borrowed[r]==0)
      {
        if(result[r]==2)
        {
          dcount += 1; // deprecated
          dfound[r] = guesskey[r];  // save value
          dmark[r] = 1; // mark as found
          remposs[r] = 1; // the only possibility left
          poss[r][0] = guesskey[r]; // save value
        }
        if(result[r]==1) // remove from this position(digit)
        {
          int f=0;
          for(int i=0;i<remposs[r];i++)
          {
            if(guesskey[r]==poss[r][i])
            {
              for(int rem=i;rem<remposs[r];rem++)
              {
                poss[r][rem] = poss[r][rem+1];
              }
              remposs[r] -= 1;
              if(remposs[r]<1)remposs[r]=1; // just in case
              f=1;
            }
            if(f==1)break;
          }
        }
      }

      if(result[r]==0) // remove from all positions
      {
        for(int d=1;d<=DIGITS;d++)
        {
          for(int b=0;b<remposs[d];b++)
          {
            if(poss[d][b]==guesskey[r])
            {
              remposs[d] -= 1;
              if(remposs[d]<0)remposs[d]=0; // again;just in case
              for(int rem=b;rem<remposs[d];rem++)
              {
                poss[d][rem]=poss[d][rem+1];
              }
            }
          }
        }
      }
    }
  }

  // borrows
//  borrows = 0;
//  for(int i=1;i<=DIGITS;i++)
//  {
//    if(dmark[i])borrows++;
//  }
// 
//  // borrows = foundcount(dmark);
//  if(borrows>0 and borrows<DIGITS)
//  {
//    int unfounds=0;
//    int lendfrom[DIGITS+1][2];
//    int borrowto[borrows+1];
//    for(int i=1;i<=DIGITS;i++) // copy the unsorted remposs-array
//    {
//      if(!dmark[i] and remposs[i]>1)  // only the unfound digits and if more than 1 solutions left
//      {
//        unfounds++;
//        lendfrom[unfounds][1]=remposs[i];
//        lendfrom[unfounds][2]=i;
//      }
//    }
//    if(unfounds>1) // sort if more than one
//    {
//      for(int i=1;i<unfounds;i++) 
//      {
//        for(int s=i+1;s<=unfounds;s++)
//        {
//          if(lendfrom[s][1]>lendfrom[i][1]) // sort it descending
//          {
//            int temp1=lendfrom[i][1];
//            int temp2=lendfrom[i][2];
//            lendfrom[i][1]=lendfrom[s][1];
//            lendfrom[i][2]=lendfrom[s][2];
//            lendfrom[s][1]=temp1;
//            lendfrom[s][2]=temp2;
//          }
//        }
//      }
//    }
//    for(int b=1;b<=DIGITS;b++)
//    {
//      int unfound=0;
//      if(dmark[b]) // borrow found position
//      {
//        unfound++;
//        if(unfound>unfounds)unfound=1; //wrap
//        {
//          remposs[b]=lendfrom[unfound][1];
//          for(int bor=0;bor<remposs[b];bor++)
//          {
//            poss[b][bor]=poss[lendfrom[unfound][2]][bor];
//          }
//          borrowed[b]=1;
//          result[b]=0; //reset result for this digit
//        }
//      }
//    }
//  }
//

}



// the guessing game
void makeaguess(int guesses, int dcount, int mostdiffs, int dfound[], int dmark[], int guesskey[], int result[], int remposs[], int poss[][BASE])
{
  int step;
  int biggest=0;
  int comb[DIGITS+1];  // saved path with most different combination
  int scan[DIGITS+1];  // current tested path


  // if found all...
  if(foundcount(dmark)>=DIGITS)
  {
    for(int i=1;i<=DIGITS;i++)
    {
      guesskey[i] = dfound[i];
    }
 }
 else // Guess a new code
 {

    // Find the combination with the most nr of differences
    // The uber-supah scan-algorithm
    biggest = 0;
    int temp;
    for(int i=1;i<=DIGITS;i++)scan[i]=0;
    int ende;
    do
    {
      temp=0;
      for(int a=1;a<DIGITS;a++)
      {
        for(int b=a+1;b<=DIGITS;b++)
        {
          if(abs(poss[a][scan[a]]-poss[b][scan[b]])>0)temp++;
        }
      }
      if(temp>biggest)
      {
        biggest=temp;
        for(int s=1;s<=DIGITS;s++)
        {
          comb[s]=scan[s]; // save path
        }
      }
      scan[DIGITS]++; //increment last pointer
      for(int s=DIGITS-1;s>0;s--)
      {
        if(scan[s+1]>=remposs[s+1])scan[s]++;
      }
      ende=1;
      for(int s=1;s<=DIGITS;s++)
      {
        if(scan[s]<remposs[s])ende=0;
        if(scan[s]>=remposs[s])scan[s]=0;
      }
    }while(!ende and biggest<mostdiffs);
//    }while(!ende);
    // the new guess
    for(int s=1;s<=DIGITS;s++)guesskey[s]=poss[s][comb[s]];

  }
    
}


int foundcount(int dmark[])
{
    int jall = 0;
    for(int i=1;i<=DIGITS;i++)
    {
      if(dmark[i])jall++;
    }
    return jall;
}
Sikkerhetsklarert
Sitat av 10goto10
Pjukern:

Ok, skal prøve.
Vis hele sitatet...
Det der var jo DEN avhandlingen jo

Ble en del klokere når jeg skjønner tankegangen din bedre, men fortsatt så sliter jeg litt med å forstå alt.
Jeg skjønner oppgaven helt greit, og vet hva jeg må få programmet til å gjøre, men hvordan jeg skal utrykke det i f.eks c++ klarer jeg ikke.

Kjapt spm, hvor i kilden din spesifiserer du at det er 0-F som er mulige tegn? (ser at space linjen noen ganger outputer en "G")
Sist endret av Pjukern; 1. september 2007 kl. 19:02.
Pjukern:

Det var litt av tankegangen ihvertfall. Nå er det ikke dermed sagt at det den beste selvsagt. Det er jo om å gjøre å finne på et eller annet lurt system, det er jo det man prøver på. Programmerings-språk er egentlig ikke så nøye i dette tilfellet. TheGEEKmeister leder vel an med sin python-ting på 5.7 i snitt.


Ditt kjappe spørsmål: Jupp, det er min "uberhex"-funksjon som ikke stopper på F
Veldig simpel, ingen grensesjekking.. jeg kunne selvsagt bare ha skrevet ut tall isteden på akkurat "space"-linja. Ville blitt litt mer rotete bare (i og med at jeg ikke har lært meg å formattere output... Alternativt er det bare for å forvirre hehe)
Det er kun antall muligheter som er igjen for den siffer-plassen. Til å begynne med 16 (G) muligheter (0 - 15)..

Konstanten BASE spesifiserer base-16 (0 - F).
Her er mitt bidrag - følger ikke output-standarden som er gitt i OP, mer ment for å benchmarke - den har så langt et gjennomsnitt på ca 5,58. Noen bedre?

http://pastebin.ca/679069
Imponerende!
Har ikke hatt tid til å lese gjennom koden din skikkelig, men får se om jeg får tid i helga
Sorely beaten...enn så lenge

Ikke verst det! hvor mange runs?

Har en aldri så liten logisk brist i min egen kodeløser-kode, men håper å få ned snittet noe etterhvert.