Ero sivun ”Python 2/Wikishakkisivu” versioiden välillä

Poistettu sisältö Lisätty sisältö
Raimondo (keskustelu | muokkaukset)
Raimondo (keskustelu | muokkaukset)
Ei muokkausyhteenvetoa
Rivi 8:
====Tehtävän määrittely====
Suunnittele ohjelma seuraava_asema.py, joka saa parametreinä tiedostonimen ja shakkisiirron ja tuottaa niiden perusteella uuden tiedoston. Parametrinä annetu tiedosto sisältää shakkilautamallineella esitetyn aseman ja shakkisiirto on lyhyellä algebrallisella notaatiolla esitetty tiedoston asemassa mahdollinen siirto. Uusi tiedosto sisältää shakkilautamallineen, jossa annettu siirto on toteutettu. Mitään virhetarkistuksia ei tässä tehtävässä tarvitse ohjelmoida. Ellei oppikirjasta löydy kaikkia tarvitsemiasi tietoja, niin etsi ne muista lähteistä ja täydennä myös oppikirjaa puuttuvilla tiedoilla.
 
====Ratkaisun ideointia====
Lopullisen ratkaisun löydyttyä seuraavat koodiharjoitelmat tiivistetään ja siistitään yksityiskohtien toteutusvaihtoehtoja havainnollistaviksi esimerkeiksi.
 
{{hidden begin|title=Shakkilautamallineen lukeminen tiedostosta|toggle=right}}
Seuraavan kuvan mukainen shakkilauta
 
{{Šakkilauta|=
|
|
|=
8 |rd|nd|bd|qd|kd|bd|nd|rd|=
7 |pd|pd|pd|pd|pd|pd|pd|pd|=
6 | | | | | | | | |=
5 | | | | | | | | |=
4 | | | | | | | | |=
3 | | | | | | | | |=
2 |pl|pl|pl|pl|pl|pl|pl|pl|=
1 |rl|nl|bl|ql|kl|bl|nl|rl|=
a b c d e f g h
|
}}
 
voidaan tuottaa seuraavalla wiki-koodilla
<source lang="Python">
{{Šakkilauta|=
|
|
|=
8 |rd|nd|bd|qd|kd|bd|nd|rd|=
7 |pd|pd|pd|pd|pd|pd|pd|pd|=
6 | | | | | | | | |=
5 | | | | | | | | |=
4 | | | | | | | | |=
3 | | | | | | | | |=
2 |pl|pl|pl|pl|pl|pl|pl|pl|=
1 |rl|nl|bl|ql|kl|bl|nl|rl|=
a b c d e f g h
|
}}
</source>
 
Alustava idea on kopioida lähtöruudussa oleva nappulatieto kohderutuun ja merkitä lähtöruutu tyhjäksi. Tehtävä kannattaa ratkaista ehkä kaksivaiheisesti niin, että ensin se ratkaistaan pitkää aggebrallista notaatiota käyttävälle siirtoparametrille, koska siitä näkee sekä lähtö että kohderuudut. Toisessa vaiheessa pitää kehittää vielä lähtöruudun päättely lyhyestä algebrallisesta notaatiosta.
 
Talletetaan aluksi edellä oleva shakkilautamallinekuvaus tekstitiedistoon <tt>asema.txt</tt> ja yritetään tulostaa se pythonilla seuraavalla ohjelmalla.
 
<source lang="Python">
# lueasema.py
# Avataan tiedosto asema0.txt lukemista varten
f_peliaema = open('asema0.txt', 'r')
# Luetaan koko tiedosto merkkijonoksi s_peliasema
s_peliasema = f_peliaema.read()
# Suljetaan tiedosto f_peliaema - tiedosto voidaan sulkea heti kun se on luettu
f_peliaema.close()
# Tulostetaan merkkijono s_peliasema
print(s_peliasema)
</source>
 
Esimerkki pitkästä merkintätavasta:
 
1.e2-e4 e7-e5 2.Lf1-c4 Rb8-c6 3.Dd1-h5 Rg8-f6?? 4.Dh5xf7X
 
{{hidden end|toggle=right}}
 
{{hidden begin|title=mahdollisten osaratkaisujen testausta|toggle=right}}
<source lang="Python">
# lueasema.py
# Avataan tiedosto asema0.txt lukemista varten
f_peliaema = open('Lauta.txt', 'r')
# Luetaan koko tiedosto merkkijonoksi s_peliasema
s_peliasema = f_peliaema.read()
# Suljetaan tiedosto f_peliaema - tiedosto voidaan sulkea
# heti kun se on luettu
f_peliaema.close()
# Tulostetaan merkkijono s_peliasema
print(s_peliasema)
# Käytetään merkkijonoon split-funktiota, joka pätkii
# tekstin rivinvaihtojen (\n) kohdilta listaksi.
l1 = s_peliasema.split('\n')
# Luodaan lista Lauta ja lisataan sen alkioiksim jokainen
# mekkijonon s_peliasema merkki.
Lauta = []
for i in s_peliasema:
Lauta.extend(i)
# tulostetaan listan lauta pituus
print len(Lauta)
# Luodaan tyhja ruudut niminen dictionary, jonka avaimina
# on ruutujen posituiotunnukset ja arvoiksi voidaan antaa
# nappuloiden shakkilautamallineen mukaiset kaksikirjaimiset koodit
ruudut = {
'a8':' ', 'b8':' ', 'c8':' ', 'd8':' ', 'e8':' ', 'f8':' ', 'g8':' ', 'h8':' ',
'a7':' ', 'b7':' ', 'c7':' ', 'd7':' ', 'e7':' ', 'f7':' ', 'g7':' ', 'h7':' ',
'a6':' ', 'b6':' ', 'c6':' ', 'd6':' ', 'e6':' ', 'f6':' ', 'g6':' ', 'h6':' ',
'a5':' ', 'b5':' ', 'c5':' ', 'd5':' ', 'e5':' ', 'f5':' ', 'g5':' ', 'h5':' ',
'a4':' ', 'b4':' ', 'c4':' ', 'd4':' ', 'e4':' ', 'f4':' ', 'g4':' ', 'h4':' ',
'a3':' ', 'b3':' ', 'c3':' ', 'd3':' ', 'e3':' ', 'f3':' ', 'g3':' ', 'h3':' ',
'a2':' ', 'b2':' ', 'c2':' ', 'd2':' ', 'e2':' ', 'f2':' ', 'g2':' ', 'h2':' ',
'a1':' ', 'b1':' ', 'c1':' ', 'd1':' ', 'e1':' ', 'f1':' ', 'g1':' ', 'h1':' ',
}
# Taman jalkeen sijoitetaan nappuloiden kodit taulukkoon jne....
</source>
{{hidden end|toggle=right}}
 
{{hidden begin|title=lisää mahdollisten osaratkaisujen testailuja|toggle=right}}
<source lang="Python">
#---------------------------------------
# tyhjan laudan alustus
#---------------------------------------
sarakkeet = ["a", "b", "c", "d", "e", "f", "g", "h"]
rivit = ["1", "2", "3", "4", "5", "6", "7", "8"]
lauta = [] # laudan indeksilista a1, a2, ... h7, h8
for s in sarakkeet:
for r in rivit:
lauta.append(s+r)
asema = {} # laudan ruutujen miehitys
ruutu = {}
for i in lauta:
ruutu = {i: ' '} # oletussisalto on tyhja
asema.update(ruutu)
#--------------------------------------------
# lisataan nappulat tyhjalle laudalle alkuasemaan
#---------------------------------------------
# 8 |rd|nd|bd|qd|kd|bd|nd|rd|=
# 7 |pd|pd|pd|pd|pd|pd|pd|pd|=
# 6 | | | | | | | | |=
# 5 | | | | | | | | |=
# 4 | | | | | | | | |=
# 3 | | | | | | | | |=
# 2 |pl|pl|pl|pl|pl|pl|pl|pl|=
# 1 |rl|nl|bl|ql|kl|bl|nl|rl|=
# a b c d e f g h
 
asema['a1'] = 'rl'
asema['b1'] = 'nl'
asema['c1'] = 'bl'
asema['d1'] = 'ql'
asema['e1'] = 'kl'
asema['f1'] = 'bl'
asema['g1'] = 'nl'
asema['h1'] = 'rl'
 
asema['a2'] = 'pl'
asema['b2'] = 'pl'
asema['c2'] = 'pl'
asema['d2'] = 'pl'
asema['e2'] = 'pl'
asema['f2'] = 'pl'
asema['g2'] = 'pl'
asema['h2'] = 'pl'
 
asema['a8'] = 'rd'
asema['b8'] = 'nd'
asema['c8'] = 'bd'
asema['d8'] = 'qd'
asema['e8'] = 'kd'
asema['f8'] = 'bd'
asema['g8'] = 'nd'
asema['h8'] = 'rd'
 
asema['a7'] = 'pd'
asema['b7'] = 'pd'
asema['c7'] = 'pd'
asema['d7'] = 'pd'
asema['e7'] = 'pd'
asema['f7'] = 'pd'
asema['g7'] = 'pd'
asema['h7'] = 'pd'
 
#-----------------------------------------
# tulostetaan laudan asema
#-----------------------------------------
# HUOM! Sanakirjan alkioiden jarjestys vaihtelee
# ja alkioihin voi viitata vain avaimella
 
for nappula in asema.items():
print nappula
print len(asema)
 
#-----------------------------------------------
# suoritetaan avaussiirto e2-e4 ja tulostetaan uusi asema
#------------------------------------------------
asema['e4'] = asema['e2']
asema['e2'] = ' '
print '---------------------------'
print asema['e4']
print asema['e2']
print '---------------------------'
for nappula in asema.items():
print nappula
print len(asema)
</source>
{{hidden end|toggle=right}}
 
{{hidden begin|title=Nappulatietojen poiminta suoraan merkkijonosta|toggle=right}}
<source lang="Python">
# -*- coding: cp1252 -*-
ruutujono='''
{{Šakkilauta|=
|
|
|=
8 |rd|nd|bd|qd|kd|bd|nd|rd|=
7 |pd|pd|pd|pd|pd|pd|pd|pd|=
6 | | | | | | | | |=
5 | | | | | | | | |=
4 | | | | | | | | |=
3 | | | | | | | | |=
2 |pl|pl|pl|pl|pl|pl|pl|pl|=
1 |rl|nl|bl|ql|kl|bl|nl|rl|=
a b c d e f g h
|
}}
'''
print ruutujono
print 'a8', ruutujono[32:34],
print 'b8', ruutujono[35:37],
print 'c8', ruutujono[38:40],
print 'd8', ruutujono[41:43],
print 'e8', ruutujono[44:46],
print 'f8', ruutujono[47:49],
print 'g8', ruutujono[50:52],
print 'h8', ruutujono[53:55]
 
print 'a7', ruutujono[63:65],
print 'b7', ruutujono[66:68],
print 'c7', ruutujono[69:71],
print 'd7', ruutujono[72:74],
print 'e7', ruutujono[75:77],
print 'f7', ruutujono[78:80],
print 'g7', ruutujono[81:83],
print 'h7', ruutujono[84:86]
 
print 'a6', ruutujono[94:96],
print 'b6', ruutujono[97:99],
print 'c6', ruutujono[100:102],
print 'd6', ruutujono[103:105],
print 'e6', ruutujono[106:108],
print 'f6', ruutujono[109:111],
print 'g6', ruutujono[112:114],
print 'h6', ruutujono[115:117]
 
print 'a5', ruutujono[125:127],
print 'b5', ruutujono[128:130],
print 'c5', ruutujono[131:133],
print 'd5', ruutujono[134:136],
print 'e5', ruutujono[137:139],
print 'f5', ruutujono[140:142],
print 'g5', ruutujono[143:145],
print 'h5', ruutujono[146:148]
 
print 'a4', ruutujono[156:158],
print 'b4', ruutujono[159:161],
print 'c4', ruutujono[162:164],
print 'd4', ruutujono[165:167],
print 'e4', ruutujono[168:170],
print 'f4', ruutujono[171:173],
print 'g4', ruutujono[174:176],
print 'h4', ruutujono[177:179]
 
print 'a3', ruutujono[187:189],
print 'b3', ruutujono[190:192],
print 'c3', ruutujono[193:195],
print 'd3', ruutujono[196:198],
print 'e3', ruutujono[199:201],
print 'f3', ruutujono[202:204],
print 'g3', ruutujono[205:207],
print 'h3', ruutujono[208:210]
 
print 'a2', ruutujono[218:220],
print 'b2', ruutujono[221:223],
print 'c2', ruutujono[224:226],
print 'd2', ruutujono[227:229],
print 'e2', ruutujono[230:232],
print 'f2', ruutujono[233:235],
print 'g2', ruutujono[236:238],
print 'h2', ruutujono[239:241]
 
print 'a1', ruutujono[249:251],
print 'b1', ruutujono[252:254],
print 'c1', ruutujono[255:257],
print 'd1', ruutujono[258:260],
print 'e1', ruutujono[261:263],
print 'f1', ruutujono[264:266],
print 'g1', ruutujono[267:269],
print 'h1', ruutujono[270:272]
</source>
{{hidden end|toggle=right}}
 
{{hidden begin|title=Haetaan tiedostosta ja tehdään alkusiirto|toggle=right}}
<source lang="Python">
# -*- coding: cp1252 -*-
# lueasema.py
# Avataan tiedosto asema0.txt lukemista varten
f_peliaema = open('asema0.txt', 'r')
# Luetaan koko tiedosto merkkijonoksi s_peliasema
s_peliasema = f_peliaema.read()
# Suljetaan tiedosto f_peliaema - tiedosto voidaan sulkea heti kun se on luettu
f_peliaema.close()
# Tulostetaan merkkijono s_peliasema
print " \n ALKUASEMA \n"
print(s_peliasema)
 
#-----------------------------------------------
# suoritetaan avaussiirto e2-e4 ja tulostetaan uusi asema
#------------------------------------------------
 
uusi_asema = s_peliasema[0:167] \
+ s_peliasema[229:232] \
+ s_peliasema[170:229] \
+ ' ' \
+ s_peliasema[231:310]
#s_peliasema[168:170] = s_peliasema[229:232] # asema['e4'] = asema['e2']
#s_peliasema[230:232] = ' ' # asema['e2'] = ' '
 
print " \n Asema avauksen e2-e4 jälkeen \n"
print(uusi_asema)
 
#--------------------------------------------------------
# Etsitään laudan rivien alkunumerot ja tulostetaan rivit
#--------------------------------------------------------
# -*- coding: cp1252 -*-
print " \n Asemalaudalla avauksen e2-e4 jälkeen (toinen toteuus) \n"
 
for n in range(len(uusi_asema)):
if uusi_asema[n] != '8':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
for n in range(len(uusi_asema)):
if uusi_asema[n] != '7':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
 
for n in range(len(uusi_asema)):
if uusi_asema[n] != '6':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
for n in range(len(uusi_asema)):
if uusi_asema[n] != '5':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
for n in range(len(s_peliasema)):
if s_peliasema[n] != '4':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
for n in range(len(uusi_asema)):
if uusi_asema[n] != '3':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
for n in range(len(uusi_asema)):
if uusi_asema[n] != '2':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
for n in range(len(uusi_asema)):
if uusi_asema[n] != '1':
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
print " a b c d e f g h"
</source>
{{hidden end|toggle=right}}
 
{{hidden begin|title=Sama uudelleen funktiota käyttäen|toggle=right}}
<source lang="Python">
# -*- coding: cp1252 -*-
# Funktio rivi(rno)
def rivi(rno):
for n in range(len(uusi_asema)):
if uusi_asema[n] != rno:
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
 
# Avataan tiedosto asema0.txt lukemista varten
f_peliaema = open('asema0.txt', 'r')
# Luetaan koko tiedosto merkkijonoksi s_peliasema
s_peliasema = f_peliaema.read()
# Suljetaan tiedosto f_peliaema - tiedosto voidaan sulkea heti kun se on luettu
f_peliaema.close()
# Tulostetaan merkkijono s_peliasema
print " \n ALKUASEMA \n"
print(s_peliasema)
 
#-----------------------------------------------
# suoritetaan avaussiirto e2-e4 ja tulostetaan uusi asema
#------------------------------------------------
 
uusi_asema = s_peliasema[0:167] \
+ s_peliasema[229:232] \
+ s_peliasema[170:229] \
+ ' ' \
+ s_peliasema[231:310]
#s_peliasema[168:170] = s_peliasema[229:232] # asema['e4'] = asema['e2']
#s_peliasema[230:232] = ' ' # asema['e2'] = ' '
 
print " \n Asema avauksen e2-e4 jälkeen \n"
print(uusi_asema)
 
#--------------------------------------------------------
# Etsitään laudan rivien alkunumerot ja tulostetaan rivit
#--------------------------------------------------------
# -*- coding: cp1252 -*-
print " \n Asemalaudalla avauksen e2-e4 jälkeen (toinen toteuus) \n"
 
rivi('8')
rivi('7')
rivi('6')
rivi('5')
rivi('4')
rivi('3')
rivi('2')
rivi('1')
print " a b c d e f g h"
 
</source>
{{hidden end|toggle=right}}
 
{{hidden begin|title=Ensimmäinen esimerkkiratkaisun karvalakkiversio|toggle=right}}
Tämä on ensimmäinen esimerkkiratkaisun karvalakkiversio. Tästä puuttuu vielä mm. parametrivälityksen toteutus. Ohjelma lukee nyt shakkilautamallineen tiedostosta asema0.txt suorittaa avauksen e2 e4 ja tallettaa muokatun aseman tiedostoon asema1.txt
 
;Ohjelmakoodi:
 
<source lang="Python">
# -*- coding: cp1252 -*-
# Funktio rivi(rno)
def rivi(rno):
for n in range(len(uusi_asema)):
if uusi_asema[n] != rno:
pass
else:
print uusi_asema[n],\
uusi_asema[n+3:n+5],\
uusi_asema[n+6:n+8],\
uusi_asema[n+9:n+11],\
uusi_asema[n+12:n+14],\
uusi_asema[n+15:n+17],\
uusi_asema[n+18:n+20],\
uusi_asema[n+21:n+23],\
uusi_asema[n+24:n+26]
 
# Avataan tiedosto asema0.txt lukemista varten
f_peliaema = open('asema0.txt', 'r')
# Luetaan koko tiedosto merkkijonoksi s_peliasema
s_peliasema = f_peliaema.read()
# Suljetaan tiedosto f_peliaema - tiedosto voidaan sulkea heti kun se on luettu
f_peliaema.close()
# Tulostetaan merkkijono s_peliasema
print " \n Alkuasaema \n"
print(s_peliasema)
 
#-----------------------------------------------
# suoritetaan avaussiirto e2-e4 ja tulostetaan uusi asema
#------------------------------------------------
 
uusi_asema = s_peliasema[0:167] \
+ s_peliasema[229:232] \
+ s_peliasema[170:229] \
+ ' ' \
+ s_peliasema[231:310]
#s_peliasema[168:170] = s_peliasema[229:232] # asema['e4'] = asema['e2']
#s_peliasema[230:232] = ' ' # asema['e2'] = ' '
 
print " \n Asema avauksen e2-e4 jälkeen \n"
print(uusi_asema)
 
#--------------------------------------------------------
# Talletaan muokattu tiedosto takaisin uudella nimellä
#--------------------------------------------------------
 
tiedosto = open('asema1.txt', 'w') # avataan kirjoitusta varten
tiedosto.write(uusi_asema) # kirjoitetaan teksti tiedostoon
tiedosto.close() # suljetaan tiedosto
</source>
 
;Testituloste:
<source lang="Python">
 
>>>
Alkuasaema
 
{{Šakkilauta|=
|
|
|=
8 |rd|nd|bd|qd|kd|bd|nd|rd|=
7 |pd|pd|pd|pd|pd|pd|pd|pd|=
6 | | | | | | | | |=
5 | | | | | | | | |=
4 | | | | | | | | |=
3 | | | | | | | | |=
2 |pl|pl|pl|pl|pl|pl|pl|pl|=
1 |rl|nl|bl|ql|kl|bl|nl|rl|=
a b c d e f g h
|
}}
 
Asema avauksen e2-e4 jälkeen
 
{{Šakkilauta|=
|
|
|=
8 |rd|nd|bd|qd|kd|bd|nd|rd|=
7 |pd|pd|pd|pd|pd|pd|pd|pd|=
6 | | | | | | | | |=
5 | | | | | | | | |=
4 | | | | |pl| | | |=
3 | | | | | | | | |=
2 |pl|pl|pl|pl| |pl|pl|pl|=
1 |rl|nl|bl|ql|kl|bl|nl|rl|=
a b c d e f g h
|
}}
>>>
</source>
{{hidden end|toggle=right}}
 
==Jatkohommat==
{{Šakkilauta|=
|tright
|Yläotsikkoteksti
|=
| | | | | | | | |=
| | | | | | | | |=
| | | | | | | | |=
| | | | | | | | |=
| | | | | | | | |=
| | | | | | | | |=
| | | | | | | | |=
| | | | | | | | |=
|Alaotsikkoteksti
}}
 
===Shakkilauta-maallineen tarkempi analyysi===
Rivi 678 ⟶ 64:
;Koodi:
 
<source lang="Python">
# -*- coding: cp1252 -*-
 
#-----------------------------------------------------------
# Testilohko, joka tulostaa alkuperäisen tiedoston sisällön
Rivi 753 ⟶ 139:
print " \n ==== asema1.txt ==== \n"
print(tulos)
</source>
 
;Testitulosteet:
<source lang="Python">
 
>>>
Rivi 795 ⟶ 182:
 
>>>
</source>
 
 
==== Toisen vaiheen ratkaisu ====