Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Joka kolmas merkki listasta

Sivun loppuun

AbuRamal [14.10.2019 14:34:35]

#

Elikkäs olis tehtävänä koodata pythonilla funktio, joka tulostaa satunnaisesta merkkijonosta joka kolmannen merkin, kunnes on tulostanut kaikki merkit.

Tällasen oon saanu aikaseks:

def jokaKolmas(s):
    lista = list(s)
    i = 0
    while len(lista) > 0:
        if i % 2 == 0:
            print lista[i % len(lista)]
            lista.pop(i % len(lista))



        i += 1

Koodi toimii 1. kierroksella oikein, mutta toisella kierrokselle mentäessä on ongelmia.

Esimerkkitulostus, kun merkkijono: ofefhu1
>o
>f
>1
>e
>u
>f
>h

Eli toivoisin johdatusta ratkaisuun, mutten varsinaisesti täysin suoraa ratkaisua.

Mod. huom.: Alun perin esimerkkinä oli annettu ai34esdj -> a4d3jsie.

peran [14.10.2019 15:12:09]

#

Ilmeisesti ongelmana on se, että kun i:n arvo tulee suuremmaksi kuin listan pituus, niin silloin pitäisi myös i:n arvoa pienentää.

AbuRamal [14.10.2019 15:57:19]

#

Aattelin, et se i pitäs ekan kierroksen jälkeen resetoida, mutta miten voin tietää, millon 1 kierros on ohi?

Grez [14.10.2019 16:04:34]

#

Mun mielestä tehtävänanto on vähän vajaa tai ainakaan sen ja esimerkin välillä ei oo logiikkaa.

Eli jos ajatellaan että joka kolmas alkaa 1. merkistä niin

ai34esdj
^  ^  ^  => a 4 d
Jäljellä olevista samalla logiikalla
i3esj
^  ^  => i s

Kuitenkin esimerkkitulosteessa on "3 j". Jos ekalla kierroksella "joka kolmas merkki" on merkit 1., 4. ja 7. niin millä logiikalla ne toisella kierroksella oliskin 2. ja 5.?

Sinänsä mä tekisin kaksi sisäkkäistä looppia. Ulompi pyörisi kunnes merkkijono on tyhjä ja sisempi poppaa merkit indeksissä 0, 2, 4, 6, 8 jne kunnes ei oo enää popattavaa.

Tämähän vastaisi myös tehtävänantoa melko kirjaimellisesti:
"tulostaa satunnaisesta merkkijonosta" => merkkijonon alustus
"joka kolmannen merkin," => sisempi looppi
"kunnes on tulostanut kaikki merkit." => ulompi looppi

Tronic [14.10.2019 16:45:52]

#

Et tarvitse kuin s[::3]. Funktioksi kirjoittaminen ja tulostaminen jätetään harjoitustehtäväksi.

https://www.datadependence.com/2016/05/python-sequence-slicing-guide/

Metabolix [14.10.2019 16:47:15]

#

Jos tulkitaan tehtävänantoa ystävällisesti esimerkkitulosteen kautta, niin ilmeisesti on tarkoitus aina tulostaa yksi merkki ja siirtää kaksi seuraavaa merkkijonon loppuun odottamaan.

def jokaKolmas(s):
	while len(s) > 0:
		print(s[0])
		s = s[3:] + s[1:3]

Jos tehtävän haluaa tehdä indekseillä (ilman merkkijonon muokkaamista), täytyy pitää kirjaa tulostetuista indekseistä ja joka kierroksella korottaa nykyistä indeksiä kolmella ja sitten vielä hakea kyseisestä kohdasta alkaen seuraava ei-tulostettu indeksi. Helpointa on siis muokata merkkijonoa, kuten edellä.

Toisaalta tehtävänannon voisi kirjaimellisesti tulkita niin, että todellakin tulostetaan vain alkuperäisen merkkijonon joka kolmatta merkkiä.

def jokaKolmasKirjaimellisesti(s):
	tulostetut = set()
	while len(tulostetut) != len(s):   # kunnes kaikki on tulostettu
		for i in range(0, len(s), 3):  # joka kolmas merkki:
			print(s[i])                # - tulostetaan
			tulostetut.add(i)          # - pidetään kirjaa

Loogisesti tässä saadaan aina tulostettua vain joka kolmas merkki, ei koskaan kaikkia merkkejä, ja näin ollen koodia voi vielä optimoida:

def jokaKolmasKirjaimellisesti(s):
	while True:
		for i in range(0, len(s), 3):
			print(s[i])

AbuRamal [14.10.2019 17:06:51]

#

En oo varma oliko toi esimerkki väärin, mut nyt ainaki 100%varmasti oikein. Idea siis, että tulostaa joka kolmannen sillain, että kaikki merkit käydään läpi.

Esim.

ofefhu1




kierros = kun käydään merkkijono kerran läpi

tulostetaan
1. kierros o,f,1
2. kierros e,u
3. kierros f,h

Metabolix [14.10.2019 17:18:59]

#

Edelleenkin on mahdotonta tulostaa yhtä aikaa ”joka kolmas merkki” ja ”kaikki merkit”. Pitää määritellä kysymys jotenkin tarkemmin. Millä logiikalla valitaan seuraava merkki sen jälkeen, kun ensimmäinen 1/3 on tulostettu? Jos tästä on jokin selvä tehtävänanto, olisi nyt viisainta kertoa se alkuperäinen tehtävänanto eikä omia muunnelmia siitä.

Tuo viimeinen esimerkkisi sekoittaa pakkaa vielä entisestään. Tuossa tulostetaan ensin joka kolmas alkaen indeksistä 0, sitten alkaen indeksistä 2 ja lopuksi alkaen indeksistä 1. Tämän toteuttamiseen riittää kolme silmukkaa, ei tarvita yhtään listapoppia. (Ei tarvita edes omia silmukoita, jos käytetään tuota Tronicin mainitsemaa ::3-temppua.)

Jos jostain syystä selvän tehtävänannon kertominen on mahdotonta, voisitko edes kertoa oikeat vastaukset kaikkiin näihin tapauksiin: "a", "ab", "abc", "abcd", "abcde", "abcdef".

AbuRamal [14.10.2019 17:22:00]

#

Määrittele funktio jokaKolmas(s) joka ottaa parametrina merkkijonon, ja tulostaa merkkijonon merkit omille riveilleen, joka kolmas merkki kerrallaan alkaen ensimmäisestä. Merkkijonon lopusta jatketaan aina alkuun. Voit luottaa matematiikkaan sokeasti, että jos tulostat len(s) verran merkkejä, niin koko merkkijono tulee tulostettua.

Esimerkkitulostus, kun merkkijono: ofefhu1
>o
>f
>1
>e
>u
>f
>h

Siinä suora kopio tehtävänannosta

Metabolix [14.10.2019 17:34:42]

#

Jaa, no tehtävänannon ideana on varmaan tämä:

# Indeksisilmukalla:
for i in range(len(s)):
  print(s[(3 * i) % len(s)])

# Hauskemmin:
for c in (s * 3)[::3]:
  print(c)

Tässä on nyt sellainen aika suuri vika, että jos merkkijonon merkkien määrä on kolmella jaollinen, tulostus on väärä. Esimerkiksi merkkijonolla "abc" tulostuksena on "a", "a", "a".

Ehkäpä tehtävän tekijän mielestä ”voit luottaa matematiikkaan sokeasti” tarkoittaa samaa kuin ”hei yritetään kaikki tehdä samanlainen bugi koodiin”.

AbuRamal [14.10.2019 17:37:49]

#

Kiitos Metabolix!!

Juuri tämä oli ideana. Seuraavalla kerralla pitäis varmaan pistää tehtävänanto samantien.

Tronic [14.10.2019 19:34:39]

#

Olisko tällainen? Aika mielettömältä tuo tehtävä kyllä vaikuttaa.

for ch in s[::3] + s[2::3] + s[1::3]:
    print(ch)

Metabolix [14.10.2019 19:45:58]

#

Tronic, mutta tuohan ei taas toimi, jos merkkijonon pituus on 3n+2, vaan silloin pitää olla aloitusindeksit 0–1–2. Eli oikea ratkaisu olisi tämä:

for c in s[::3] + s[-len(s)%3::3] + s[len(s)%3::3]:
	print(c)

Tronic [15.10.2019 09:44:33]

#

Ei oikein selvinnyt mitä tarkoitetaan "merkkijonon lopusta jatketaan aina alkuun", mutta ilmeisesti sitten tuota.

Grez [15.10.2019 11:20:29]

#

Tästä tehtävästä kyllä tulee huonossa mielessä kouluajat mieleen. Meillä nyt ei ollut tietotekniikassa varsinaisia tehtäviä, mutta matematiikasta ja fysiikasta muistuu mieleen nämä "paskat tehtävänannot" joissa jää ihan epäselväksi mitä halutaan. Kokeissa kun ei voinut kysyä tarkennusta tehtäviin ja toisaalta ei halunnut riskeerata pisteiden menettämistä, niin joutui joskus antamaan vaikka neljä eri vastausvaihtoehtoa eri oletuksilla.

Jaska [18.10.2019 09:29:43]

#

Grez kirjoitti:

Meillä nyt ei ollut tietotekniikassa varsinaisia tehtäviä, mutta matematiikasta ja fysiikasta muistuu mieleen nämä "paskat tehtävänannot" joissa jää ihan epäselväksi mitä halutaan.

Jaa. Minun kokemukseni mukaan matematiikassa oli eksaktit tehtävänannot. Ei tullut mieleen tehtäviä, jotka olisi olleet monitulkintaisia. Matemaatikot kun opiskelevat asiat järjestelmällisesti aksioomista lähtien. Sen sijaan teoreettisessa fysiikassa ja tietotekniikassa oli sellaisia asioita, joita en meinannut ymmärtää. Esimerkiksi fysiikassa oli vaikea keksiä, miksi joku integraali suppenee tai tietojenkäsittelyssä en tajunnut, miten asymptoottisessa notaatiossa voidaan yhtäsuuruus ja joukkoon kuuluvuuden symboli vaihtaa keskenään. Harmillista, kun en tiedä oppimateriaaleja, jossa tietojenkäsittelyn teoriaa olisi aksiomatisoitu ja johdettu kunnolla.

qeijo [18.10.2019 10:01:00]

#

Jaska kirjoitti:

(18.10.2019 09:29:43): ”– –” Jaa. Minun kokemukseni mukaan mate­ma­tii­kassa...

:o

Grez [18.10.2019 10:34:33]

#

Jaska kirjoitti:

Jaa. Minun kokemukseni mukaan matematiikassa oli eksaktit tehtävänannot.

No se varmaan riippuu ihan opettajasta, että miten hyvin hyvin hän osaa ilmaista itseään tehtäviä kirjoittaessa. Tai ainakin silloin neljännesvuosisata sitten opettajamme teki itse kokeet.

Lisäksi ainakin meillä oli kirjakaupasta ostetun matematiikan kirjan välissä monistelappunen, jossa oli listattu noin 30 korjausta tehtäviin ja mallivastauksiin.

Jaska kirjoitti:

Matemaatikot kun opiskelevat asiat järjestelmällisesti aksioomista lähtien.

Tarkoittaako tuo myös sitä, että matemaatikot eivät tee virheitä tai esim. unohda mainita tärkeitä reunaehtoja tehtäviä laatiessaan? Ehkä myöskään matematiikan opettajat tai edes kirjojen kirjoittajat eivät ole varsinaisesti matemaatikkoja.

Jaska [18.10.2019 18:48:53]

#

Grez kirjoitti:

Tarkoittaako tuo myös sitä, että matemaatikot eivät tee virheitä tai esim. unohda mainita tärkeitä reunaehtoja tehtäviä laatiessaan? Ehkä myöskään matematiikan opettajat tai edes kirjojen kirjoittajat eivät ole varsinaisesti matemaatikkoja.

Periaatteessa on mahdollista, että joku kirjoittaa huolimattomasti. Ainakaan viimeksi kun opiskelin, niin ainakin tenttitehtävät olivat matematiikassa pääosin yksikäsitteisiä. Yhden virheellisen tehtävän muistan. Joitakin muita puutteita löysin aikanaan, mutta vähemmän kuin fysiikasta tai tietojenkäsittelystä.

Toki kaikkia reunaehtoja ei voi aina ottaa huomioon. Joskus voi myös miettiä, kuinka yleisillä oletuksella joku asia on voimassa. Tutkimuksessa on varmaan aika paljon sellaista, että ei ehditä tutkimaan kaikkea, ja joskus joku viittaa väärään tulokseen.

Sitten on vielä Gödelin tulos, jonka mukaan kaikkea ei voi matemaatikotkaan ratkaista.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta