Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Apua salaimen tekoon

Sivun loppuun

Darwen [23.12.2006 20:58:00]

#

Aloitin Pythonilla OMC-Q nimisen osasalaimen teon.
Sen tarkoitus olisi olla osa isompaa salainta (Creato)
Mikä tässä menee väärin ? Sen pitäis: 1. laskee a,b,c ja d
2. ottaa kaksi lukua, jotka on lähimpinä nollaa ja alottaa alusta. Tämä pitäis toistua niin kauan että jokin lasketuista arvoista olisi nolla. Silmukan jälkeen sen pitäisi tulostaa c, mutta tuota tulostusta ei tule. Ohjelma jää vain päälle.

#OMC-Q moduuli Creatoon
print 'OMC-Q'
a, b, c, d, N, C, K, P = 0, 0, 0, 0, 0, 0, 0, 0

P = int(raw_input('[Salasana] = '))
K = int(raw_input('[Avain] = '))
d = a or b or c or d == 0
while d:

  a = K - P
  b = K + P
  c = a - b
  d = a + b
  N = N + 1

  vluvut = [ abs(a),abs(b),abs(c),abs(d) ]
  vluvut.sort()
  a = vluvut[0]
  b = vluvut[1]

else:
   print c

Olisko ratkaisuja ongelmaan ja neuvoja
koodin parantamiseksi ?

Pekka Karjalainen [24.12.2006 12:49:01]

#

Tein näin:

#OMC-Q moduuli Creatoon
print 'OMC-Q'
a, b, c, d, N, C, K, P = 0, 0, 0, 0, 0, 0, 0, 0

P = int(raw_input('[Salasana] = '))
K = int(raw_input('[Avain] = '))

while True:

  a = K - P
  b = K + P
  c = a - b
  d = a + b
  N = N + 1

  vluvut = [ abs(a),abs(b),abs(c),abs(d) ]
  vluvut.sort()
  a = vluvut[0]
  b = vluvut[1]

  if a*b*c*d == 0: break # joku ainakin on nolla
  else: print a,b,c,d

print c

Nyt se pysähtyy syötteellä 1 1 (c on -2)
mutta jatkaa ikuisesti syötteelä 1 2

Jälkimmäisessä tapauksessa arvot a,b,c ja d juuttuvat
arvoiksi 1 2 -2 4.

Niitä pitäisi jotenkin päivittää joka kierrokselle tavalla, jonka tiedetään loppuvan siihen, että jotkin arvot ovat nollia. En ymmärrä tällä hetkellä käyttämääsi logiikkaa.

Darwen [24.12.2006 23:25:18]

#

Huomasin että olin antanut sulle päättömän koodinpätkän. (sori)
Tällänen logiikka pitäis kuiteski tehä.

Lopullinen logiikka on: 1. Käyttäjältä kysytään Salasana (P) ja Avain (K). 2. Arvoista K ja P lasketaan summa ja erotus.
3. Laskutoimituksista saaduista arvoista a ja b otetaan myös summa ja erotus (c ja d). 4. Lisätään N:ään yksi ( N on kierrosten lukumäärä )
5. Vertaillaan muuttujien a,b,c,d itseisarvoja. [ JOS jokin itseisarvoista on nolla, niin irtaudutaan silmukasta ja sitten edellisen kierroksen c ja d summa siirretään Creaton yhdeksi muuttujaksi(Loppu). JOS itseisavoista ei löydy nollaa niin, laskutoimituksista saaduista arvoista
otetaan kaksi lukua lähinnä nollaa.
(Huom! ei itseisarvoista ). Otetut luvut sijoitetaan muuttujien K ja P paikalle niin että lähimpänä nollaa oleva luku on K ja toiseksi lähin P. Jos luvut ovat yhtä kaukana nollasta mutta erimerkkisiä (-x ja x) otetaan ylempänä laskutoimituksissa oleva K:ksi ja alempana oleva P:ksi. Sitten silmukka aloitetaan alusta kohdasta 2. uusilla K ja P arvoilla ] -- Kun N on 3,7,11,15... (Joka toinen pariton) niin a:han lisätään yksi joten a = K - P + 1. Tämän toimenpiteen tarkoituksena on parantaa `Sekoita ja hajoita`-periaatetta. ¤¤ OMC-Q tarkoitus on olla XORrauksen tapainen menetelmä, ei mikään monimutkainen salausalgoritmi. Creatosta taas pitäisi tulla sellainen kryptoanalyytikoiden painajainen.

Pekka Karjalainen [25.12.2006 13:37:49]

#

Okei, tuo ei vieläkään aukene ihan yhdeltä lukemalta, mutta kyllähän sitä kerkeää tässä illalla vähän pohtia. Otan viestisi talteen koneelleni ja luen sen tarkemmin, kun on hieman enemmän aikaa.

Tuosta testistä voisin vielä sanoa, että

d = a or b or c or d == 0

joka on koodissasi, ei testaa sitä, miltä ehkä näyttää. Se on tosi vain kun kaikki a,b,c ja d ovat nollia. Sanoit kuitenkin, että (vain) jokin arvoista pitää olla nolla.

Esittämäni tulotestaus on yksi tapa testata, että ainakin yksi on nolla. Se käyttää hyväksi nollalla kertomisen ominaisuutta (että tulo, jossa on ainkain yksi nolla on aina nolla), joka ei toimi muilla luvuilla. Jos haluat testata, että jossain muuttujissa esiintyy jokin arvo, voit tehdä myös näin.

a,b,c,d = range (3,7) # a = 3, b = 4 jne.
4 in [a,b,c,d]

Jälkimmäinen on boolean-arvoinen testi ja saa arvon True, koska 4 on jäsen listassa, joka saadaan muuttujista a,b,c,d. Se voisi esiintyä esim. if-lauseessa.

Jos tätä ominaisuutta ei olisi Pythonissä, pitäisi kirjoittaa C-kielen tapaan.

a==0 || b==0 || c==0 || d==0

Tai tämän sijasta voisi tehdä apufunktion, mikäli olisi C-kielessä järkevin tapa.

Tämä oli vähän Python-kohtaista juttua. Tuohon on varmasti muitakin tapoja. C-kielessäkin taitaa olla parempi, joka tuli nyt juuri lopuksi mieleen. Vaan ei kannata mennä siihen enää.

Kirjoitan illalla toisen viestin.

Pekka Karjalainen [25.12.2006 18:20:10]

#

Ei suju vieläkään. Olisiko sinulla esimerkki miten laskut menevät vaikkapa, kun valitaan arvot P = 1, K = 2?

#OMC-Q moduuli Creatoon
print 'OMC-Q'

P = int(raw_input('[Salasana] = '))
K = int(raw_input('[Avain] = '))
N = 0

def vertailu (x,y):
  "Vertailee itseisarvojen suuruutta."
  return cmp (abs(x),abs(y))

while True:

  a = K - P
  b = K + P
  c = a - b # c = -2*P ??
  d = a + b # d =  2*K ??

  N = N + 1

  # Kun N on 3,7,11,15... (Joka toinen pariton)
  # niin a:han lisataan yksi joten a = K - P + 1.
  if N%4==3: a += 1

  vluvut = [a,b,c,d]
  vluvut.sort(cmp=vertailu)
  K,P = vluvut[:2] # kaksi ekaa

  if a*b*c*d == 0: break # joku ainakin on nolla

  if N%100000==0:
    print N, "kierrosta mennyt"
    print "viimeisimmat arvot ovat", vluvut

print c

Darwen [25.12.2006 21:59:38]

#

N = 1
K = 2 P = 1

2 - 1 = 1
2 + 1 = 3
1 - 3 = -2
1 + 3 = 4
-------------------
N = 2
K = 1 P = -2

1 - (-2) = 3
1 + (-2) = -1
3 - (-1) = 4
3 + (-1) = 2
-------------------
N = 3 ( a:han lisätään yksi )
K= -1 P = 2

-1 - 2 + 1 = -2
-1 + 2 = 1
-2 - 1 = -3
-2 + 1 = -1
-------------------
N = 4
K = 1 P = -1

1 - (-1) = 2
1 + (-1) = 0 <-- Nolla joten edellisen kierroksen
2 - 0 = 2        c ja d summa on vastaus eli -3 + -1 = -4
2 + 0 = 2

Vastaus: Selväteksti 1 on avaimella 2 käännettynä -4

Hyvä että laitoit mut laskemaan käsin noita käsin nimittäin mä huomasin yhen uuden asian: - Edellisessä viestissä mä sanoin " Jos luvut ovat yhtä kaukana nollasta mutta erimerkkisiä (-x ja x) otetaan ylempänä laskutoimituksissa oleva K:ksi ja alempana oleva P:ksi". Tätä vertailua ei koodiin tarvita. Jos haluat selityksen, pyydä !!!

Pekka Karjalainen [26.12.2006 11:03:21]

#

Hyvä että selvensit. Nythän sain sen toimimaan juuri kuvaamallasi tavalla. Toivottavasti se toimii myös muilla arvoilla kuten pitää.

Minun olisi mm. pitänyt huomata, että tuo N:n arvosta johtuva a:n kasvatus pitää tehdä ennen kuin lasketaan c ja d. Luin ohjeesi liian katkonaisesti, mutta selvisihän se nyt. Siksi myöskään c:n ja d:n laskemista ei voi suoraan korvata P:stä ja K:sta laskemalla näillä kierroksilla.

Tässä ohjelmassa on paljon väliaikatulosten ja koko laskuhistorian tulostusta, joka varmaankin kannattaa poistaa myöhemmin. Jos jostain Python-rakenteesta on kysyttävää, voit kysyä erikseen. Luulisin, että se on aika selvä. Kaksi kohtaa:

1) lista pitää kopioida, kun se laitetaan historiaan, jotta siihen tehdyt muutokset (järjestäminen) eivät näy historiassa

2) vluvut.sort(cmp=vertailu)

tässä cmp=vertailu on avainsana-argumentti. Katsomalla help(list.sort) näet, että tämä funktio hyväksyy sellaisia. Kyseisen argumentti kertoo, minkä funktion avulla lista järjestetään ja vertailun tulee palauttaa lukuja -1,0 tai 1 järjestyksen mukaan. Testaamalla huomaat varmasti, että tämä vertailu-funktio antaa haluttuja tuloksia. (Tulkissa on helppo testata).

Jos algoritmi pysähtyy heti annetuilla arvoilla, toteutuksessani ovat edellisen kierroksen c ja d silloin molemmat nollia. Jos haluat niille muut default-arvot, ne voi laittaa kohtaan vanhac, vanhad = 0,0.

#OMC-Q moduuli Creatoon
print 'OMC-Q'

P = int(raw_input('[Salasana] = '))
K = int(raw_input('[Avain] = '))
N = 0

def vertailu (x,y):
  "Vertailee itseisarvojen suuruutta."
  return cmp (abs(x),abs(y))

historia = []
vanhac, vanhad = 0,0

while True:

  N = N + 1

  print "K ja P", K, P
  a = K - P
  b = K + P

  # Kun N on 3,7,11,15... (Joka toinen pariton)
  # niin a:han lisataan yksi joten a = K - P + 1.
  if N%4==3: a += 1

  c = a - b
  d = a + b

  vluvut = [a,b,c,d]
  historia.append(list(vluvut)) # list tekee kopion

  vluvut.sort(cmp=vertailu)
  K,P = vluvut[:2] # kaksi ekaa

  if a*b*c*d == 0: break # joku ainakin on nolla
  else: vanhac, vanhad = c,d
  if N%100000==0:
    print N, "kierrosta mennyt"
    print "viimeisimmat arvot ovat", vluvut

print "Haluttu summa on", vanhac, "+", vanhad, "=", vanhac+vanhad
print "Aiemmilla kierroksilla a,b,c ja d olivat:"
for rivi in historia:
  print rivi

Esimerkkiajo

OMC-Q
[Salasana] = 1
[Avain] = 2
K ja P 2 1
K ja P 1 -2
K ja P -1 2
K ja P 1 -1
Haluttu summa on -3 + -1 = -4
Aiemmilla kierroksilla a,b,c ja d olivat:
[1, 3, -2, 4]
[3, -1, 4, 2]
[-2, 1, -3, -1]
[2, 0, 2, 2]
>>>

Yst. terv. Koppis

Darwen [26.12.2006 17:53:25]

#

Koodi on ihan toimiva ja se itse asiassa täyttää kaikki kriteerit. Aluksi mä katoin että se toistaa ihan kauheesti, mutta se onkin hyvä juttu
Kiitän ja kumarran sekä lopuksi tokaisen että saatan tarvita apua Creaton kanssa kun olen saanut muut laskelmat loppuun. Jos tarvitsen apua, yritän välittää kysymyksen suoraan sulle :D

Pekka Karjalainen [26.12.2006 19:17:10]

#

Ole vain hyvä :-)

Minulle voi mailatakin (profiilissa on osoite), jos en satu heti vastaamaan. Nyt kun oli joulu, niin kerkesi netissäkin haahuilla. Muuten en aina lue juttuja läheskään joka päivä, ja asia voi jäädä huomaamatta.

On täällä kyllä muitakin Python-taitoisia, että yleisesti kannattaa varmasti kysyä.


Sivun alkuun

Vastaus

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

Tietoa sivustosta