Ohjelmointi 2/2013, demo 1 vastauksia

5-6. Numeron muuttaminen

Arvosanana

Oletetaan tällä kertaa yksinkertaisuuden vuoksi, että syöttö on oikeaa muotoa eli numero ja mahdollisesti jokin merkeistä "+-½".

Tällöin algoritmi voisi olla vaikkapa:

1. ota syötön numero-osa => n
2. ota syötön viimeinen merkki =>m
3. jos m = '+' niin n = n+0.25
   jos m = '½' niin n = n+0.5
   jos m = '-' niin n = n-0.25
4. talletettava numero on n

Huonoa edellä on ehkä runsas määrä 'jos'-lauseita. Toisaalta edullista olisi, jos voitaisiin antaa selvä taulukko siitä, miten muutetaan kirjaimen perusteella. Katsotaan ensin kuitenkin päinvastaista muunnosta

1. olkoon arvosana desimaalisena a
2. otetaan a:n kokonaisosa => n
3. otetaan a:n desimaaliosa => d
4. jos d = 0.25 niin m="+"
   jos d = 0.5  niin m="½"
   jos d = 0.75 niin m="-" ja n = n+1
   muuten m=""
5. muutetaan n merkkijonoksi => s  (eli esim. 6 = >"6")
6. yhdistetään tulokseksi s ja m (eli "6" ja "+" => "6+")


Huonoa on jälleen pitkä jos-osa ja se että yhdessä pitää n:ää muuttaa ja muissa ei. Jospa keräämmekin ominaisuudet taulukkoon:

+--------+---------+----------+ 
| merkki |  desim  | vähennys |
+--------+---------+----------+
|  "+"   |  0.25   |   0      |
|  "½"   |  0.5    |   0      |
|  "-"   |  0.75   |   1      |
|  ""    |  0.0    |   0      |
+--------+---------+----------+ 

Nyt teksti->numero muunnos olisi:

1. ota syötön numero-osa => n
2. ota syötön viimeinen merkki =>m
3. etsi m taulukosta ja löytyneeltä riviltä (tai viimeiseltä) laske:
    n = n + desim - vähennys
4. talletettava numero on n


Vastaavasti muunnos numero->teksti olisi:

1. olkoon arvosana desimaalisena a
2. otetaan a:n kokonaisosa => n
3. otetaan a:n desimaaliosa => d
4. etsi desimaaliosa taulukosta ja löytyneen rivin mukaan 
   laske n = n + vähennys
5. muutetaan n merkkijonoksi => s  (eli esim. 6 = >"6")
6. yhdistetään tulokseksi s ja merkki (eli "6" ja "+" => "6+")

Mitä etua tästä saatiin? Ainakin se, että jos Takapajulan Peruskoulun hutkinnon mutkistuksessa päätetään lisätä arvosteluun muodot

6#  = 6.33
6!  = 5.66
niin lisäyksessä tarvitsee vain muuttaa taulukkoa! Miten?

7. Nimen muuttaminen

Nimen järjestyksen vaihtaminen

Käytetään aliohjelmaa, joka katkaisee merkkijonon valitun merkin kohdalta ja merkiksi valitaan välilyönti. Näin nimestä saadaan kaksi osaa:
"Ankka"  ja "Aku"
tulostetaan peräkkäin jonot
"Aku", " " ja "Ankka"
jolloin tulos näyttäisi näytöllä seuraavalta:
Aku Ankka

Otettava huomioon seuraavat erikoistapaukset:
0 merkkijonoa eli syöte on tyhjä  "" => ""
1 merkkijono, esim. Pele             => "Pele"
2 merkkijonoa, normaali tapaus eli Ankka Aku => "Aku Ankka"
n merkkijonoa, esim. Palo Jukka Pekka => "Jukka Pekka Palo"



On tietysti nimiä, joista voi tulla ongelmia. Esimkerkiksi aatelisnimet. Tämän takia käytännössä etunimi(nimet) ja sukunimi(nimet) talletetaan eri kenttiin. Tai vähintään käytetään etu/sukunimen välissä eri erotinmerkkiä.

B1. Kokonaislukujen neliöjuuria

1   package demo.d1;
2   
3   /**
4    * Lasketaan mitkä kokonaisluvut ovat jonkin luvun neliöitä.
5    * @author Vesa Lappalainen
6    * @version 1.0, 10.01.2003
7    * <pre>
8    * Aluksi mietitään miten arvot käyttäytyvät
9    *   n  sqrt(n)
10   *   0    0
11   *   1    1
12   *   2    1.4...
13   *   3    1.7...
14   *   4    2
15   *   5    2.2...
16   *   6    2.4...
17   *   7    2.6...
18   *   8    2.8...
19   *   9    3
20   * 
21   *  Eli oikeastaan kannattaakin lukuja käydä lävitse tuolla
22   *  neliöjuuripuolella...  Silloin niiden neliöt ovat ne halutut
23   *  kokonaisluvut.
24   * </pre>
25   */
26  public class Koksqrt {
27  
28      private static void tulosta(int n1, int n2) {
29          System.out.println(" " + n1 + " => " + n2);
30      }
31  
32  
33      //-------------------------------------------------------------------------
34      private static void tulostaNeliojuuret1(int raja) {
35          // Matemaatikon versio
36          int n = 0, ns = 0;
37          while (n <= raja) {
38              tulosta(n,ns);
39              ns++;
40              n = ns * ns;
41          }
42      }
43  
44  
45      //-------------------------------------------------------------------------
46      private static void tulostaNeliojuuret2(int raja) {
47          // "Raakavoimaratkaisu"
48          int ns,n = 0;
49          double dns;
50          while (n <= raja) {
51              dns = Math.sqrt(n);
52              ns = (int)Math.round(dns);
53              if ( dns == ns)
54                  tulosta(n,ns);
55              n++;
56          }
57      }
58  
59  
60      //-------------------------------------------------------------------------
61      private static void tulostaNeliojuuret3(int r) {
62          // "Hakkerin" ratkaisu
63          for (int i=0,j=0;i<r;++j,i=j*j) System.out.println(" "+i+" => "+j);
64      }
65  
66  
67      //-------------------------------------------------------------------------
68      private static void tulostaNeliojuuret4(int raja) { // NOPMD rajaa ei käytetä
69          // M$ ratkaisu, jossa päätetty että 100 riittää :-)
70          tulosta(0,0);
71          tulosta(1,1);
72          tulosta(4,2);
73          tulosta(9,3);
74          tulosta(16,4);
75          tulosta(25,5);
76          tulosta(36,6);
77          tulosta(49,7);
78          tulosta(64,8);
79          tulosta(80,9); // Kuuluu M$-ratkaisuun, korjataan ver 3.5 :-)
80          tulosta(100,10);
81      }
82  
83  
84      /**
85       * Testataan eri versioita laskennasta
86       * @param args ei käytössä
87       */
88      public static void main(String[] args) {
89          tulostaNeliojuuret1(1000);
90          tulostaNeliojuuret2(1000);
91          tulostaNeliojuuret3(1000);
92          tulostaNeliojuuret4(1000);
93      }
94  
95  }
96  
[JavaDoc-muoto] [Alkuperäinen java]

G1-5. 6 numeroisten lukujen kaikki kombinaatiot

1   package demo.d1;
2   
3   import java.util.ArrayList;
4   // import java.util.Arrays;
5   import java.util.List;
6   
7   /**
8    * Etsitään mikä on todennäköisyys voittaa seuraavassa pelissä:
9    * On 3:n värisiä palloja.  Niistä poimitaan 4 kappaletta.
10   * Sitten poimitaan vielä 2 kappaletta. Pelissä voittaa
11   * mikäli nämä 2 palloa löytyvät 4 pallon joukosta.
12   * Eli jos molemmat pallot ovat punaisia, pitää neljän pallon
13   * joukossa olla myös olla 2 punaista (yksi ei riitä).
14   * 
15   * Ratkaisu tehdään etsimällä ensin kaikki kuuden pallon
16   * mahdolliset joukot.  Näistä lasketaan monellako
17   * kaksi ensimmäistä kuuluu loppuun joukkoon.
18   * @author vesal
19   * @version 2.1.2012
20   */
21  public class Kombinaatiot {
22  
23      /**
24       * Lasketaan ja tulostetaan kaikki 6 pallon kombinaatiot
25       * @param args ei käytössä
26       */
27      public static void main(String[] args) {
28          int vareja = 3;
29          int ekakoko = 4;
30          int tokakoko = 2;
31          
32          List<Integer> varienJoukko = new ArrayList<Integer>();
33          for (int i=0; i<vareja; i++) varienJoukko.add(i);
34          List<List<Integer>> kaikkiJoukot = etsiKombinaatiot(ekakoko+tokakoko,varienJoukko);
35          for (List<Integer> kombi : kaikkiJoukot)
36              System.out.println(kombi);
37              
38          /*
39          List<String> varienJoukko = Arrays.asList("pun","vih","sin");
40          List<List<String>> kaikkiJoukot = etsiKombinaatiot(ekakoko+tokakoko,varienJoukko);
41          for (List<String> kombi : kaikkiJoukot)
42              System.out.println(kombi);
43          */    
44      }
45  
46      
47      /**
48       * Etsii kaikki n kokoiset joukot, jossa on alkioita joukosta valinnat
49       * @param n kuinka suuri ajoukkoja etsitään
50       * @param valinnat jokko alkioita joita voidaan valita
51       * @return kaikkien kombinaatioiden joukko
52       * @example
53       * <pre name="test">
54       * #import java.util.List;
55       *   List<String> valinnat = Arrays.asList("a","b","c");
56       *   List<List<String>> kombit = etsiKombinaatiot(2,valinnat);
57       *   int i=0;
58       *   kombit.get(i++).toString() === "[a, a]";
59       *   kombit.get(i++).toString() === "[a, b]";
60       *   kombit.get(i++).toString() === "[a, c]";
61       *   kombit.get(i++).toString() === "[b, a]";
62       *   kombit.get(i++).toString() === "[b, b]";
63       *   kombit.get(i++).toString() === "[b, c]";
64       *   kombit.get(i++).toString() === "[c, a]";
65       *   kombit.size() === 9;
66       * </pre>
67       */
68      public static<T> List<List<T>> etsiKombinaatiot(int n, List<T> valinnat) {
69          List<List<T>> tulos = new ArrayList<List<T>>();
70          int[] indeksit = new int[n]; // alustettu 0:illa
71          int m = valinnat.size();
72          while ( true ) {
73              List<T> rivi = new ArrayList<T>();
74              for (int i:indeksit)
75                  rivi.add(valinnat.get(i));
76              tulos.add(rivi);
77              if ( !kasvata(indeksit,m) ) break;
78          }
79          return tulos;
80      }
81  
82      
83      /**
84       * Kasvattaa indeksitaulukon "arvoa" yhdellä.
85       * Kukin indeksi voi olla luku 0-(m-1).
86       * @param indeksit taulukko, jota "kasvatetaan"
87       * @param m mikä on rajana yhdelle luvulle
88       * @return true jos pystyi kasvattamaan
89       * @example
90       * <pre name="test">
91       * #import java.util.Arrays;
92       *   int[] ind = new int[2];
93       *   Arrays.toString(ind) === "[0, 0]"; kasvata(ind,3)=== true; 
94       *   Arrays.toString(ind) === "[0, 1]"; kasvata(ind,3)=== true; 
95       *   Arrays.toString(ind) === "[0, 2]"; kasvata(ind,3)=== true; 
96       *   Arrays.toString(ind) === "[1, 0]"; kasvata(ind,3)=== true; 
97       *   Arrays.toString(ind) === "[1, 1]"; kasvata(ind,3)=== true; 
98       *   Arrays.toString(ind) === "[1, 2]"; kasvata(ind,3)=== true; 
99       *   Arrays.toString(ind) === "[2, 0]"; kasvata(ind,3)=== true; 
100      *   Arrays.toString(ind) === "[2, 1]"; kasvata(ind,3)=== true; 
101      *   Arrays.toString(ind) === "[2, 2]"; kasvata(ind,3)=== false; 
102      *   Arrays.toString(ind) === "[0, 0]"; 
103      * </pre>
104      */
105     public static boolean kasvata(int[] indeksit, int m) {
106         int n = indeksit.length;
107         for (int i=n-1; i>=0; i--) {
108             indeksit[i]++;
109             if ( indeksit[i] < m ) return true;
110             indeksit[i] = 0;
111         }
112         return indeksit[0] != 0;
113     }
114 
115 }
116 
[JavaDoc-muoto] [Alkuperäinen java]