1   package tentti09;
2   
3   
4   import java.util.Scanner;
5   
6   /**
7    * Ohjelma kysyy kaksi nimeä ja laskee nimien perusteella
8    * kaksinumeroisen rakkausprosentin. Rakkausprosentti lasketaan
9    * laskemalla "LOVES"-sanan jokaisen kirjaimen lukumäärät kummassakin
10   * nimessä. Esimerkiksi nimissä "Lotta" ja "Esko" on yhteensä
11   * <pre>
12   *  -  1 kpl L-kirjainta
13   *  -  2 kpl O-kirjaimia
14   *  -  0 kpl V-kirjainta
15   *  -  1 kpl E-kirjainta
16   *  -  1 kpl S-kirjainta.
17   * </pre>
18   * Suur- ja pienaakkosilla ei ole merkitystä. 
19   * Kirjaimien lukumäärät summataan vierekkäisten kirjaimien lukumäärien 
20   * kanssa yhteen, jolloin jäljelle jää neljä lukumäärää. 
21   * Jos lukumäärien summasta tulee kaksi- tai useampinumeroinen, 
22   * niin silloin luvun numerot summataan yhteen 
23   * (esimerkiksi luvusta 12 tulee 3). 
24   * Vierekkäisten kirjaimien lukumäärien summaamista jatketaan kunnes 
25   * jäljellä on kaksi lukua. Nämä kaksi lukua muodostavat rakkausprosentin.  
26   * @author Ohj1 tuntiopet
27   * @version 16.12.2009
28   */
29  public class Rakkauslaskuri {
30  
31      /** Sana jonka kirjaimiin verrataan */
32      public static final String RAKKAUSSANA = "LOVES";
33  
34      
35      /**
36       * Laskee yhteen luvun numerot
37       * @param luku tutkittava luku
38       * @return luvun numeroiden summa
39       * @example
40       * <pre name="test">
41       *   summaaNumerot(0) === 0
42       *   summaaNumerot(12) === 3
43       *   summaaNumerot(123) === 6
44       *   summaaNumerot(78) === 15
45       * </pre>
46       */
47      public static int summaaNumerot(int luku) {
48          int summa = 0;
49          int n = luku;
50          while ( n > 0 ) {
51              summa += n % 10;
52              n = n / 10;
53          }
54          return summa;
55      }
56      
57      /**
58       * Muuttaa luvun yksinumeroikseksi laskemalla luvun numerot
59       * yhteen niin kauan että tulos on yksinumeroinen.
60       * @param luku tutkittava luku
61       * @return luvun numeroiden summa (aina yksi numero)
62       * @example
63       * <pre name="test">
64       *   yksiNumeroinenSumma(1)   === 1;
65       *   yksiNumeroinenSumma(12)  === 3;
66       *   yksiNumeroinenSumma(123) === 6;
67       *   yksiNumeroinenSumma(78)  === 6;
68       * </pre>
69       */
70      public static int yksiNumeroinenSumma(int luku) {
71          int tulos = luku;
72          while ( tulos > 9 ) tulos = summaaNumerot(tulos);
73          return tulos;
74      }
75      
76      /**
77       * Laskee taulukon vierekkäiset luvut yhteen ja palauttaa
78       * uuden taulukon, jossa on vierekkäisten lukujen summa.
79       * Jos summan luvusta tulee kaksi tai useampinumeroinen, 
80       * sen numerot lasketaan yhteen kunnes se on yksinumeroinen.
81       * @param a laskettava taulukko
82       * @return vierekkäisten summa (yhtä lyhyempi kuin a)
83       * @example
84       * <pre name="test">
85       * Arrays.toString(laskeVierekkaisetYhteen(new int[]{1}))     === "[]";
86       * Arrays.toString(laskeVierekkaisetYhteen(new int[]{1,1}))   === "[2]";
87       * Arrays.toString(laskeVierekkaisetYhteen(new int[]{2,3,5})) === "[5, 8]";
88       * </pre>
89       */
90      public static int[] laskeVierekkaisetYhteen(int[] a) {
91          int[] a2 = new int[a.length - 1]; // Lukujen määrä vähenee aina yhdellä.
92          // Käydään kerralla läpi kaksi vierekkäistä alkiota.
93          // Lopetetaan kun jälkimmäinen (j) on lopussa.
94          for (int i = 0, j = 1; j < a.length; i++, j++) {
95              a2[i] = yksiNumeroinenSumma(a[i] + a[j]);
96          }
97          return a2;
98      }
99  
100     /**
101      * Laskee kuinka monta mitäkin sanan kirjainta löytyy jonosta.
102      * @param sana jonka kirjaimia tutkitaan 
103      * @param jono josta kirjaimia etsitään
104      * @return kirjainten lukumäärät kokonaislukutaulukossa
105      * @example
106      * <pre name="test">
107      * #import java.util.Arrays;
108      *   Arrays.toString(laskeKirjaimet("apu","saapas"))  === "[3, 1, 0]";
109      *   Arrays.toString(laskeKirjaimet("apu",""))        === "[0, 0, 0]";
110      *   Arrays.toString(laskeKirjaimet("Apua","saapas")) === "[0, 1, 0, 3]";
111      * </pre>
112      */
113     public static int[] laskeKirjaimet(String sana,String jono) {
114         int[] a = new int[sana.length()];
115         for (int si = 0; si < a.length; si++) {
116             char c = sana.charAt(si);
117 
118             int lkm = 0;
119             for (int ji=0; ji<jono.length(); ji++)
120                 if ( jono.charAt(ji) == c ) lkm++;
121 
122             a[si] = lkm;
123         }
124         return a;
125     }
126 
127     /**
128      * Lasketaan sanojen rakkausprosentti.
129      * @param nimi1
130      * @param nimi2
131      * @return nimien rakkausprosentti
132      * 
133      * @example
134      * <pre name="test">
135      * laskeRakkausprosentti("Lotta","Esko") === 86
136      * laskeRakkausprosentti("Viivi-Loviisa","Lasse-Sylvester") === 39
137      * laskeRakkausprosentti("SUSU","VOSSO") === 99
138      * </pre>
139      */
140     public static int laskeRakkausprosentti(String nimi1, String nimi2) {
141         int[] luvut = laskeKirjaimet(RAKKAUSSANA, (nimi1 + nimi2).toUpperCase());
142 
143         while (luvut.length > 2) {
144             luvut = laskeVierekkaisetYhteen(luvut);
145         }
146         return luvut[0]*10 + luvut[1];
147     }
148 
149     /**
150      * Lasketaan rakkausprosentti käyttäjän syötteistä
151      * @param args ei käytössä
152      */
153     public static void main(String[] args) {
154         System.out.println("Ohjelma laskee kahdesta nimestä rakkausprosentin.");
155         Scanner scan = new Scanner(System.in);
156         System.out.print("Anna ensimmäinen nimi: ");
157         String nimi1 = scan.nextLine();
158         System.out.print("Anna toinen nimi: ");
159         String nimi2 = scan.nextLine();
160         System.out.printf("Rakkausprosenttinne on %d!%n",
161         laskeRakkausprosentti(nimi1, nimi2));
162     }
163 
164 }
165