Skip to content

Commit

Permalink
Ääkköset poistettu. Käyttöohje päivitetty.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chamion committed Oct 22, 2017
1 parent d201cac commit 10ba42d
Show file tree
Hide file tree
Showing 23 changed files with 137 additions and 141 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,15 @@
Selvittää Blackjack pelin jakajan käden todennäköisyydet annetulle korttipakalle.

## Versio 1.0
Ensimmäinen toimiva versio on ladattavissa. Julkaisuun kuuluu .jar-tiedosto, käyttöohje (jonka voi lukea GitHubissakin) ja esimerkkisyötetiedosto.
Ensimmäinen toimiva versio on ladattavissa. Julkaisuun kuuluu .jar-tiedosto, käyttöohje (jonka voi lukea GitHubissakin) ja esimerkkisyötetiedosto.

## Versio 1.1
Loppupalautusversio.


Verrattuna 1.0 versioon:


* prosentin murto-osan optimoidumpi.
* bugikorjauksia. Tulosten ei enää pitäisi mennä väärin, kun otetaan absurdi määrä merkitseviä numeroita.
* Ääkköset on poistettu, sillä ne aiheuttivat kryptisiä ongelmia.
4 changes: 2 additions & 2 deletions dokumentaatio/Käyttöohje.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ java -jar BJKA.jar



Oletusarvoisesti ohjelma etsii tiedostoa syöte.txt hakemistosta, jossa olet.
Oletusarvoisesti ohjelma etsii tiedostoa syote.txt hakemistosta, jossa olet.
Jos haluat käyttää jotain muuta syötettä, anna syötetiedosto argumenttina.


Esim.
```
java -jar BJKA.jar toinen_syöte.txt
java -jar BJKA.jar toinen_syote.txt
```

## Syötetiedoston sisältö
Expand Down
7 changes: 6 additions & 1 deletion dokumentaatio/Testausdokumentti.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ Testi siis painottaa kaikkia alkukortteja yht
Käytetyllä pakalla ei ole suurta merkitystä suorituskykyyn. Pakka voi siis olla mikä tahansa.


Suorituskykytestin suorittaminen kesti ohjelmalta ajan väliltä 5ms - 10ms, mutta normaalit ajat olivat väliltä 6ms - 8ms.
~~Suorituskykytestin suorittaminen kesti ohjelmalta ajan väliltä 5ms - 10ms, mutta normaalit ajat olivat väliltä 6ms - 8ms.~~


Suorituskykytesti kestää kotikoneellani n. 4ms +- 0.2ms.
Aika on huomattavasti nopeampi, kuin optimoimattoman, Javan valmiita tietorakenteita käyttävän toteutuksen ajat.
Keskimäärin optimointi säästää arviolta 40% suoritusajassa.

# Yksikkötestit

Expand Down
2 changes: 1 addition & 1 deletion dokumentaatio/Toteutusdokumentti.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ TapahtumaSolmu koodataan taulukkoon kokonaislukukoodin avulla. Jonoon merkitää

Kokonaislukukoodi saadaan antamalla jokaiselle jakajan käden kortille lukuarvo kortin arvon perusteella (alkukorttia lukuunottamatta) ja laskemalla nämä lukuarvot yhteen.
Korttien arvoja vastaavat lukuarvot on valittu siten, että erilaisten käsien lukuarvojen summat eivät ole samat millään jakajan käsillä, joiden arvo on 16 tai pienempi.
Käytännössä keksin ne yritys-erehdys menetelmällä.
~~Käytännössä keksin ne yritys-erehdys menetelmällä.~~ optimisaatio.py-apulohjelma selvitti sopivat arvot.


Lähtösolmu on käsiteltävä erikseen Blackjack-erikoistapauksen takia. Blackjack todennäköisyydet lasketaan kovakoodatulla logiikalla lähtösolmun käsittelyssä.
Expand Down
56 changes: 28 additions & 28 deletions maven-BJKA/src/main/java/bjka/Analysoija.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,31 @@ public Analysoija() {
}

/**
* Laskee Blackjack jakajan käden todennäköisyydet.
* Laskee Blackjack jakajan kaden todennakoisyydet.
*
* @param alkukortti Jakajan käden ensimmäinen kortti.
* @param pakka Jäljellä oleva pakka, josta kortit nostetaan. Alkukortti ei
* sisälly pakkaan.
* @return Tulosvektori, joka sisältää jakajan käden todennäköisyydet
* seuraavassa järjestyksessä. [17, 18, 19, 20, 21, bust, BJ]
* @param alkukortti Jakajan kaden ensimmainen kortti.
* @param pakka Jaljella oleva pakka, josta kortit nostetaan. Alkukortti ei
* sisally pakkaan.
* @return Tulosvektori, joka sisaltaa jakajan kaden todennakoisyydet
* seuraavassa jarjestyksessa. [17, 18, 19, 20, 21, bust, BJ]
*/
public double[] analysoi(int alkukortti, Pakka pakka) {

//Päättyneet tapahtumaketjut merkataan tulosvektoriin.
//Paattyneet tapahtumaketjut merkataan tulosvektoriin.
double[] tulos = new double[]{0, 0, 0, 0, 0, 0, 0};

TapahtumaSolmu alkuSolmu = new TapahtumaSolmu(alkukortti, alkukortti == 1, 1.0, pakka);

// Jonoon lisätään tapahtumasolmut, jotka jatkuvat vielä.
//Jonon koko selvitettiin kokeilemalla yhä pienempiä arvoja, kunnes testit eivät enää menneet läpi.
// Jonoon lisataan tapahtumasolmut, jotka jatkuvat viela.
//Jonon koko selvitettiin kokeilemalla yha pienempia arvoja, kunnes testit eivat enaa menneet lapi.
Jono jono = new Jono(91);

// Tapahtumasolmut talletetaan Map-tietorakenteeseen, jotta alkion olemassaolon tarkistaminen on nopeampaa. O(1) vs. O(n)
TapahtumaSolmu[] map = new TapahtumaSolmu[2191];

int alkukoodi = 0;

// Käsitellään ensimmäinen tapahtumasolmu erikseen BJ-erikoistapauksen takia.
// Kasitellaan ensimmainen tapahtumasolmu erikseen BJ-erikoistapauksen takia.
double[] alkuTVektori = alkuSolmu.laskeTodennakoisyydet();
if (alkuSolmu.getAssa()) {
tulos[6] += alkuTVektori[0];
Expand All @@ -59,7 +59,7 @@ public double[] analysoi(int alkukortti, Pakka pakka) {
kasitteleTapahtuma(i, alkuTVektori[i], alkukoodi, alkuSolmu, jono, map, tulos);
}

// Silmukka käy läpi kaikki mahdolliset tapahtumaketjut.
// Silmukka kay lapi kaikki mahdolliset tapahtumaketjut.
while (!jono.isEmpty()) {
int seuraavaKoodi = jono.get();
kasitteleTapahtumaHaara(seuraavaKoodi, jono, map, tulos);
Expand All @@ -69,28 +69,28 @@ public double[] analysoi(int alkukortti, Pakka pakka) {
}

/**
* Käsittelee yhden lahtoSolmun lapsista. Jos lapsi on päätössolmu, se
* Kasittelee yhden lahtoSolmun lapsista. Jos lapsi on paatossolmu, se
* merkataan tulosvektoriin. Jos lapsi on tapahtumaSolmu, se tallennetaan
* map ja jono rakenteisiin.
*
* @param tapahtuma uusi kortti, joka nostettiin
* @param tapahtumaTodennakoisyys Edellisen solmun todennäköisyyden ja
* tapahtuman todennäköisyyden tulo.
* @param tapahtumaTodennakoisyys Edellisen solmun todennakoisyyden ja
* tapahtuman todennakoisyyden tulo.
* @param lahtokoodi Edellisen solmun kokonaislukukoodi
* @param lahtoSolmu Edellinen solmu
* @param jono Jono, johon uusien solmujen koodit tallennetaan
* @param map Taulukko, johon uudet solmut tallennetaan
* @param tulos Tulosvektori, johon uudet päätössolmut merkataan
* @param tulos Tulosvektori, johon uudet paatossolmut merkataan
*/
private void kasitteleTapahtuma(int tapahtuma, double tapahtumaTodennakoisyys, int lahtokoodi, TapahtumaSolmu lahtoSolmu, Jono jono, TapahtumaSolmu[] map, double[] tulos) {
// Todennäköisyysvektoreissa 10 on koodattu nollaksi. Käännetään takaisin.
// Todennakoisyysvektoreissa 10 on koodattu nollaksi. Kaannetaan takaisin.
if (tapahtuma == 0) {
tapahtuma = 10;
}

int uusiArvo = lahtoSolmu.getArvo() + tapahtuma;

// Jos jakaja jää, kirjataan tulos ja käsittely päättyy.
// Jos jakaja jaa, kirjataan tulos ja kasittely paattyy.
if (lahtoSolmu.getAssa() || tapahtuma == 1) {
if (uusiArvo >= 7 && uusiArvo <= 11) {
tulos[tulosIndeksi(uusiArvo + 10)] += tapahtumaTodennakoisyys;
Expand All @@ -108,44 +108,44 @@ private void kasitteleTapahtuma(int tapahtuma, double tapahtumaTodennakoisyys, i
boolean uusiAssa = lahtoSolmu.getAssa() || tapahtuma == 1;

if (map[uusiKoodi] != null) {
// Jos tapahtumasolmu on jo Map-oliossa, ei lisätä sitä uudestaan, vaan päivitetään vain sen todennäköisyys.
// Jos tapahtumasolmu on jo Map-oliossa, ei lisata sita uudestaan, vaan paivitetaan vain sen todennakoisyys.
map[uusiKoodi].lisaaTodennakoisyys(tapahtumaTodennakoisyys);
} else {
// Jos tapahtumasolmu ei ole Map-oliossa, lisätään se myös jonoon käsiteltäväksi.
// Jos tapahtumasolmu ei ole Map-oliossa, lisataan se myos jonoon kasiteltavaksi.
map[uusiKoodi] = new TapahtumaSolmu(uusiArvo, uusiAssa, tapahtumaTodennakoisyys, lahtoSolmu.seuraavaPakka(tapahtuma));
jono.lisaa(uusiKoodi);
}
}

/**
* Muodostaa solmun kaikki lapset ja käsittelee ne.
* Muodostaa solmun kaikki lapset ja kasittelee ne.
*
* @param lahtokoodi Jonosta poimittu solmun kokonaislukukoodi
* @param jono Jono, johon uusien solmujen koodit tallennetaan
* @param map Taulukko, johon uudet solmut tallennetaan
* @param tulos Tulosvektori, johon uudet päätössolmut merkataan
* @param tulos Tulosvektori, johon uudet paatossolmut merkataan
*/
private void kasitteleTapahtumaHaara(int lahtokoodi, Jono jono, TapahtumaSolmu[] map, double[] tulos) {

TapahtumaSolmu lahtoSolmu = map[lahtokoodi];
double[] tVektori = lahtoSolmu.laskeTodennakoisyydet();

// Käydään läpi ja käsitellään kaikki mahdolliset tapahtumat: 10, 1, 2, 3, 4, 5, 6, 7, 8, 9
// Kaydaan lapi ja kasitellaan kaikki mahdolliset tapahtumat: 10, 1, 2, 3, 4, 5, 6, 7, 8, 9
for (int i = 0; i <= 9; i++) {
kasitteleTapahtuma(i, tVektori[i], lahtokoodi, lahtoSolmu, jono, map, tulos);
}
}

/**
* Kokonaislukukoodi on summa, missä jokainen kädessä oleva kortti
* alkukorttia lukuunottamatta on lisää tietyn vakion koodiin. Vakio riippuu
* Kokonaislukukoodi on summa, missa jokainen kadessa oleva kortti
* alkukorttia lukuunottamatta on lisaa tietyn vakion koodiin. Vakio riippuu
* kortin arvosta.
*
* Vakiot on valittu siten, ettei yhteentörmäyksiä tapahdu mahdollisissa
* Blackjack käsissä.
* Vakiot on valittu siten, ettei yhteentormayksia tapahdu mahdollisissa
* Blackjack kasissa.
*
* @param kortti Kortti joka lisätään jakajan käteen.
* @return Luku, joka tulee lisätä edelliseen koodiin, jotta saadaan uuden
* @param kortti Kortti joka lisataan jakajan kateen.
* @return Luku, joka tulee lisata edelliseen koodiin, jotta saadaan uuden
* tapahtumasolmun koodi.
*/
private int koodi(int kortti) {
Expand Down
34 changes: 17 additions & 17 deletions maven-BJKA/src/main/java/bjka/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
public class Main {

/**
* Main metodi. Ks. dokumentaation käyttöohje.
* Main metodi. Ks. dokumentaation kayttoohje.
*
* @param args komentorivillä annettu syöte.
* @param args komentorivilla annettu syote.
*/
public static void main(String[] args) {
//Oletusarvo.
String syotePath = "syöte.txt";
String syotePath = "syote.txt";

//Jos käyttäjä antoi syötteen.
//Jos kayttaja antoi syotteen.
if (args.length > 0) {
//Erikoistapaus "suorituskyky" suorittaa suorituskykytestin.
if (args[0].equals("suorituskyky")) {
Expand All @@ -35,7 +35,7 @@ public static void main(String[] args) {
return;
}

//Oletusarvo korvataan syötteellä.
//Oletusarvo korvataan syotteella.
syotePath = args[0];
}

Expand All @@ -44,56 +44,56 @@ public static void main(String[] args) {
try {
lukija = new Scanner(syote);
} catch (FileNotFoundException e) {
System.out.println("Tiedostoa ei löytynyt: " + syotePath);
System.out.println("Tiedostoa ei loytynyt: " + syotePath);
return;
}

//Ensimmäinen rivi syötetiedostossa.
//Ensimmainen rivi syotetiedostossa.
int alkukortti;
try {
String rivi = lukija.nextLine();
alkukortti = Integer.parseInt(rivi);
} catch (NoSuchElementException e) {
System.out.println("Ensimmäistä riviä ei löytynyt.");
System.out.println("Ensimmaista rivia ei loytynyt.");
return;
} catch (NumberFormatException e) {
System.out.println("Ensimmäinen rivi ei ole kokonaisluku.");
System.out.println("Ensimmainen rivi ei ole kokonaisluku.");
return;
}
if (alkukortti <= 0 || alkukortti > 10) {
System.out.println("Ensimmäinen rivi ei esitä sopivaa alkukorttia.");
System.out.println("Ensimmainen rivi ei esita sopivaa alkukorttia.");
return;
}

//Toinen rivi syötetiedostossa.
//Toinen rivi syotetiedostossa.
int[] lukumaarat = new int[10];
try {
String rivi = lukija.nextLine();
//Poistetaan kaikki merkit, jotka eivät ole ',' tai lukuja.
//Poistetaan kaikki merkit, jotka eivat ole ',' tai lukuja.
rivi = rivi.replaceAll("[^\\d,]", "");
String[] sanat = rivi.split(",");
for (int i = 0; i < 10; i++) {
lukumaarat[i] = Integer.parseInt(sanat[i]);
}
} catch (NoSuchElementException e) {
System.out.println("Toista riviä ei löytynyt.");
System.out.println("Toista rivia ei loytynyt.");
return;
} catch (IndexOutOfBoundsException e) {
System.out.println("Toisessa rivissä on liian vähän argumentteja.");
System.out.println("Toisessa rivissa on liian vahan argumentteja.");
return;
} catch (NumberFormatException e) {
System.out.println("Toisen rivin argumentti ei sisältänyt lukua.");
System.out.println("Toisen rivin argumentti ei sisaltanyt lukua.");
return;
}

lukija.close();
Pakka pakka = new Pakka(lukumaarat);
Analysoija analysoija = new Analysoija();
//Lasketaan todennäköisyydet.
//Lasketaan todennakoisyydet.
double[] tulos = analysoija.analysoi(alkukortti, pakka);

//Printout.
System.out.println("Jakajan käden todennäköisyydet");
System.out.println("Jakajan kaden todennakoisyydet");
System.out.println("Alkukortti: " + alkukortti);
System.out.println("Pakka: {"
+ "10: " + lukumaarat[0]
Expand Down
16 changes: 8 additions & 8 deletions maven-BJKA/src/main/java/bjka/Pakka.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
public class Pakka {

/*
Taulukon arvot esittävät eri arvoisten korttien lukumääriä.
Taulukon arvot ovat aina järjestyksessä 10, 1, 2, 3, 4, 5, 6, 7, 8, 9
Esim. 10-arvoisten korttien lukumäärä on indeksissä 0 ja 7-arvoisten korttien lukumärä indeksissä 7.
Taulukon arvot esittavat eri arvoisten korttien lukumaaria.
Taulukon arvot ovat aina jarjestyksessa 10, 1, 2, 3, 4, 5, 6, 7, 8, 9
Esim. 10-arvoisten korttien lukumaara on indeksissa 0 ja 7-arvoisten korttien lukumara indeksissa 7.
*/
private final int[] lukumaarat;

// Korttien yhteismäärä.
// Korttien yhteismaara.
private int koko;

public Pakka(int[] lukumaarat) {
Expand All @@ -26,10 +26,10 @@ public Pakka(int[] lukumaarat) {

/**
* Laskee ja palauttaa taulukon, jossa korttien arvot ovat samassa
* järjestyksessä kuin lukumäärät-taulukossa. Todennäköisyysvektorin lukujen
* jarjestyksessa kuin lukumaarat-taulukossa. Todennakoisyysvektorin lukujen
* summa on 1.
*
* @return Vektori, joka esittää eri arvoisten korttien todennäköisyyksiä
* @return Vektori, joka esittaa eri arvoisten korttien todennakoisyyksia
* tulla nostetuksi pakasta seuraavana.
*/
public double[] todennakoisyysVektori() {
Expand All @@ -45,13 +45,13 @@ public double[] todennakoisyysVektori() {
* parametrina annettu kortti.
*
* @param kortti Kortti, joka poistetaan pakasta.
* @return Pakka, joka jää jäljelle kortin poistamisen jälkeen.
* @return Pakka, joka jaa jaljelle kortin poistamisen jalkeen.
*/
public Pakka poistaKortti(int kortti) {
kortti = kortti % 10;
int[] uudetLukumaarat = this.lukumaarat.clone();

// Lukumäärä voi mennä negatiiviseksi. Tulos on kuitenkin aina oikein (negatiivinen todennäköisyys kerrotaan aina nollalla).
// Lukumaara voi menna negatiiviseksi. Tulos on kuitenkin aina oikein (negatiivinen todennakoisyys kerrotaan aina nollalla).
uudetLukumaarat[kortti] -= 1;
return new Pakka(uudetLukumaarat);
}
Expand Down
12 changes: 6 additions & 6 deletions maven-BJKA/src/main/java/bjka/Suorituskykytesti.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ public class Suorituskykytesti {
/**
*
* @param alkuKortit analysoijan parametri alkuKortti jokaiselle
* kierrokselle. Oltava yhtä suuri kuin pakat.
* kierrokselle. Oltava yhta suuri kuin pakat.
* @param pakat analysoijan parametri pakka jokaiselle kierrokselle. Oltava
* yhtä suuri kuin alkuKortit.
* yhta suuri kuin alkuKortit.
* @param kello Kello, joka mittaa laskentaan kuluneen ajan. Parametrina
* testejä varten.
* testeja varten.
*/
public static void suorituskykytesti(int[] alkuKortit, Pakka[] pakat, KelloRajapinta kello) {
Analysoija analysoija = new Analysoija();
Expand All @@ -20,15 +20,15 @@ public static void suorituskykytesti(int[] alkuKortit, Pakka[] pakat, KelloRajap
//Aika alkaa.
aika = kello.nanoTime();

//Silmukka käsittelee kaikki alkiot parametrina annetuista taulukoista indeksi kerrallaan.
//Silmukka kasittelee kaikki alkiot parametrina annetuista taulukoista indeksi kerrallaan.
for (int i = 0; i < alkuKortit.length; i++) {
analysoija.analysoi(alkuKortit[i], pakat[i]);
}

//Aika päättyy.
//Aika paattyy.
aika = kello.nanoTime() - aika;

System.out.println("Todennäköisyyksien laskeminen jokaisella alkukortilla kesti " + aika + " nanosekuntia.");
System.out.println("Todennakoisyyksien laskeminen jokaisella alkukortilla kesti " + aika + " nanosekuntia.");
}

}
Loading

0 comments on commit 10ba42d

Please sign in to comment.