Text verschlüsseln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
vipeet
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2016, 08:56

Hallo,

vorab ich bin Python-Neuling, studiere eigentlich Biologie und bringe mir das Programmieren als Hobby bei.

Mein Ziel ist es ein Programm zu schreiben das Text umwandelt bzw verschlüsselt.

Dazu will ich jedem Buchstaben im Alphabet eine Kombination aus den Buchstaben A, U, C, G zuordnen. Diese Zuordnung kann zufällig sein. Zum Beispiel:

A = AUCG
B = UCGA
C = CCAA
D = UUUU

sowas in der Art.

Mit diesem neuen Alphabet will ich dann einen Text schreiben.

Ich habe zwar in meinem Pythonbuch einen Weg gefunden text zu verschlüsseln (nach Cäsar) aber das hilft mir irgendwie nicht weiter.

Ich danke euch!

Grüße

Patrick
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@vipeet
Der erste Schritt müsste IMHO sein, den Schlüssel zu definieren, nachdem Du die jeweiligen Buchstaben verschlüsselst. Diesen Schlüssel benötigst Du ja dann wieder, um den Text zu entschlüsseln. Dass 'A' zu einer zufälligen Kombination aus 4 Buchstaben wird, muss ja auch wieder rückwärts bekannt sein. So einen Schlüssel könnte man mit einem dictionary darstellen:

Code: Alles auswählen

In [1]: codec = {'a': 'gcua', 'A': 'AUCG', 'b': 'agcu', 'B': 'UCGA'}

In [2]: codec['a']
Out[2]: 'gcua'

In [3]: codec['B']
Out[3]: 'UCGA'
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@vipeet: Irgendwie vermisse ich in Deinem ersten Beitrag eine Frage‽ Wo liegt denn das Problem? Was hast Du schon gemacht?
vipeet
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2016, 08:56

@BlackJack: Also was ich bis jetzt gemacht habe ist eine caesar Verschlüsselung zu schreiben, aber das kommt nicht an das ran was ich mir Vorstelle. Bei dieser Verschlüsselung wird das Alphabet um 3 stellen verschoben und damit dann der Text verschlüsselt.

Ich weiß gar nicht wie ich das oben beschriebene Programm angehen soll, das ist das Problem, und die Frage ist wie löse ich das Problem.

@mutetella: Danke schon mal für den Tipp :)
BlackJack

@vipeet: Grundsätzlich musst Du das Problem in kleinere Teilprobleme zerlegen, und die dann auch wieder, solange bis die einzelnen Teilprobleme so klein sind, dass man sie mit einer Funktion mit ein paar Zeilen Code lösen kann. Einen Text, oder beliebige Bytewerte, zu verschlüsseln, kann man in diesem Fall auf das Teilproblem ein einzelnes Zeichen zu verschlüsseln herunter brechen. Denn wenn man eine Funktion hat, die ein Byte verschlüsselt, kann man sehr einfach eine Funktion schreiben, die diese Funktion auf eine Folge von Bytes anwendet und die Einzelergebnisse zu einem Gesamtergebnis zusammenfügt.

Bytewerte übrigens deswegen weil es sich hier geradezu anbietet nicht einfach nur Text, also Buchstaben zu verschlüsseln, denn mit Viererkombinationen von vier verschiedenen Buchstaben kann man 4⁴ = 256 verschiedene Werte kodieren. Und wenn man sich das klar gemacht hat, bietet es sich an die Abbildung als Abbildung von Zahlen zur Basis 256 auf Zahlen zur Basis 4 mit den ”Ziffern” A, U, C, und G statt 0, 1, 2, und 3 zu sehen. Da sowohl Quell- als auch Zielbasis eine 2er-Potenz ist, liegen Bitoperationen nahe:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from itertools import imap

ALPHABET = 'AUCG'


def encode_character(character):
    value = ord(character)
    return ''.join(
        ALPHABET[value >> i & 0b11] for i in reversed(xrange(0, 8, 2))
    )


def encode_string(string):
    return ''.join(imap(encode_character, string))


def main():
    print(encode_string('Hallo, Welt!\0'))


if __name__ == '__main__':
    main()
Ausgabe:

Code: Alles auswählen

UACAUCAUUCGAUCGAUCGGACGAACAAUUUGUCUUUCGAUGUAACAUAAAA
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

vipeet hat geschrieben:Ich weiß gar nicht wie ich das oben beschriebene Programm angehen soll, das ist das Problem, und die Frage ist wie löse ich das Problem.
Offensichtlich möchtest Du jeden Buchstaben des Alphabets in eine vierstellige Aminosäurensequenz überführen. Dafür kannst Du ein Dictionary verwenden, so wie mutetellas Ansatz (das ich allerdings nicht 'codec' nennen wollen würde).
Als Python-Neuling könnte es eine schöne Übungsaufgabe sein, anschließend eine Funktion zu schreiben, welche einen gegebenen Aminosäurenstrang wieder dechiffriert.
vipeet
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2016, 08:56

@BlackJack: WOW, danke. Das hast du ja fix hinbekommen, unglaublich! Natürlich habe ich den Code noch nicht ganz durchschaut, aber damit werde ich mich jetzt erstmal ein bisschen beschäftigen!

@kbr: Du hast fast recht :) noch ist es keine Aminosäurensequenz, sondern eine Basenabfolge, also ein DNA-Strang aus dem man rein theoretisch eine Aminosäurensequenz ableiten könnte. Du hast recht ich werde versuchen das Programm so zu erweitern das aus dieser Basenabfolge wieder Text wird. Ich danke euch!

Grüße
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

vipeet hat geschrieben: @kbr: Du hast fast recht :) noch ist es keine Aminosäurensequenz, sondern eine Basenabfolge, also ein DNA-Strang aus dem man rein theoretisch eine Aminosäurensequenz ableiten könnte.
Wäre es wegen des Us (statt T) nicht RNA?
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

nezzcarth hat geschrieben:
vipeet hat geschrieben: @kbr: Du hast fast recht :) noch ist es keine Aminosäurensequenz, sondern eine Basenabfolge, also ein DNA-Strang aus dem man rein theoretisch eine Aminosäurensequenz ableiten könnte.
Wäre es wegen des Us (statt T) nicht RNA?
@vipeet: Stimmt, es sind natürlich Basen :)
@nezzcarth: Ja, Uracil gehört zur RNA.
BlackJack

Das dekodieren in der Programmiersprache Hy (damit ich nicht aus versehen die kompletten Hausaufgaben löse ;-)):
[codebox=clojure file=Unbenannt.txt]#!/usr/bin/env hy

(def *alphabet* "AUCG")


(defn join-strings [strings] (.join "" strings))


(defn decode-digit [digit]
(try
(.index *alphabet* digit)
(except [ValueError]
(raise (ValueError (.format "digit {0!r} not in *alphabet*" digit))))))


(defn decode-character [character]
(unless (= (len character) 4)
(raise
(ValueError
(.format "character {0!r} doesn't consist of 4 \"digits\"" character))))
(chr (reduce (fn [n digit] (+ (<< n 2) (decode-digit digit))) character 0)))


(defn decode-string [string]
(setv length (len string))
(unless (zero? (% length 4))
(raise (ValueError "string length must be multiple of 4")))
(join-strings
(genexpr
(decode-character (cut string i (+ i 4)))
[i (range 0 length 4)])))


(defmain [&rest args]
(-> (decode-string "UACAUCAUUCGAUCGAUCGGACGAACAAUUUGUCUUUCGAUGUAACAUAAAA")
(repr)
(print)))[/code]
vipeet
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2016, 08:56

Guten Abend Leute,

erst einmal es handelt sich um RNA und nicht DNA ... :D und nein es ist keine Hausaufgabe!

nun habe ich mich ein bisschen mit dem Code beschäftigt, aber steige noch nicht so richtig durch, dafür bin ich noch zu frisch in der Materie. Daher habe ich nochmal versucht ein eigenes Programm zu schreiben, diesmal mit der Idee von mutetella.

Ich bin jetzt soweit das ich ein bestimmten String in eine Basenabfolge umschreiben kann.

Jetzt wollte ich das so schreiben das ich, wenn ich zum Beispiel H eingebe das Programm den Buchstaben in eine vorher bestimmte Basenabfolge ändert.

Ich habe es mit raw_input und einer Schleife versucht bin aber nicht weit gekommen...

Habt ihr eine Idee wie ich das lösen könnte?

Die Idee dahinter war dass das Programm jeden Buchstaben des Strings durchgeht und dann in die entsprechende Basenabfolge umändert.

Code: Alles auswählen

Basen = {'a': 'GCG', 'b': 'ACU', 'c': 'UGC', 'd':'GAU','e':'GAA','f':'UUC','g':'GGU','h':'CAC','i':'AUC','j':'UUA','k':'AAA','l':'UUA','m':'AUG','n':'AAU','o':'UUA','p':'CCG','q':'CAA','r':'CGA','s':'UCU','t':'ACG','u':'GUU','v':'ACG','w':'UGG','x':'AAA','y':'UAU','z':'GGG'}
Basen['a']
Basen['b']
Basen['c']
Basen['d']
Basen['e']
Basen['f']
Basen['g']
Basen['h']
Basen['i']
Basen['j']
Basen['k']
Basen['l']
Basen['m']
Basen['n']
Basen['o']
Basen['p']
Basen['q']
Basen['r']
Basen['s']
Basen['t']
Basen['u']
Basen['v']
Basen['w']
Basen['x']
Basen['y']
Basen['z']

s = "hallo"

for letter in s[1]:
    print Basen['h']
            
for letter in s[2]:
   print Basen['a']

for letter in s[3]:
   print Basen['l']

for letter in s[4]:
   print Basen['l']

for letter in s[5]:
   print Basen['o']
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Dein Ansatz mit dem Dictionary geht schon in die richtige Richtung.

Etwas idiomatischer könnte man das meiner Meinung nach vielleicht so lösen:
[codebox=python file=Unbenannt.txt]
from string import ascii_letters
from random import choice
CHARS = ('A', 'C', 'G', 'U')
TABLE = {char:''.join(choice(CHARS) for _ in range(4)) for char in ascii_letters}

def encode(s):
return ''.join(TABLE[char] for char in s)
[/code]

Code: Alles auswählen

In [15]: encode('python')
Out[15]: 'UGAGGACCUAGCUUGUAACGGCUU'
Den Teil vor der Funktionen Definition kannst du im Prinzip erst einmal ignorieren; da wird einfach nur schnell eine Übersetzungs-Tabelle erzeugt.
Das übliche Vorgehen bei solchen Ersetzungen (wenn man nicht so vorgeht wie unten beschrieben) ist, über die Zeichenkette zu iterieren, das jeweilige Zeichen als Schlüssel eines Wörterbuchs zu verwenden und die jeweiligen Werte dann zusammen zu kleben.

Zeichenketten in Python kennen auch die Methoden translate und maketrans, die das ganze noch etwas einfacher machen und zu bevorzugen sind.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@nezzcarth: str.translate funktioniert nur wenn jedes Zeichen durch genau ein anderes Zeichen ersetzt werden soll.

@vipeet: Versuche mal für Dich folgende Fragen zu beantworten: was meinst Du machen die Zeilen mit »Basen['a']«, usw.? Was machen die for-Schleifen? Für was ist die Variable »letter«?
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Sirius3 hat geschrieben:@nezzcarth: str.translate funktioniert nur wenn jedes Zeichen durch genau ein anderes Zeichen ersetzt werden soll.
Das hatte ich so auch in Erinnerung, aber:

(python 3.5.1)
[codebox=python file=test.txt]
In [1]: table
Out[1]:
{65: 'GCCC',
66: 'UAAG',
67: 'CUGU',
...
In [2]: 'ABC'.translate(table)
Out[2]: 'GCCCUAAGCUGU'
[/code]
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@nezzcarth: vipeet verwendet Python2
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Sirius3 hat geschrieben:@nezzcarth: vipeet verwendet Python2
Hab ich nicht so drauf geachtet, 'tschuldigung :( (auf meinem OS ist Python 3 der Standard). Dann weiß er jetzt, wie's dort läuft. ;) Klammern um die print-Argumente zu setzen wäre trotzdem 'ne Option...
vipeet
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2016, 08:56

Sirius3 hat geschrieben: @vipeet: Versuche mal für Dich folgende Fragen zu beantworten: was meinst Du machen die Zeilen mit »Basen['a']«, usw.? Was machen die for-Schleifen? Für was ist die Variable »letter«?
Also die Idee mit der "for Schleife" und "letter" war das python den string Buchstabe für Buchstabe durch geht und durch eine Base['x'] ersetzt.
Das funktioniert auch doch muss ich immer per hand angeben wie lang der string ist und durch welche Basen['x'] die Buchstaben ersetzt werden.
Ich weiß eben nicht wie ich das so gestallte das Python die Buchstaben von alleine erkennt und dann ersetzt.

@nezzcarth: Mhhh also irgendwie funktioniert dein code nicht bei mir? Bei mir gibt python nichts aus wenn ich das Programm starte.
BlackJack

@vipeet: Du musst eben nicht angeben ”wie lang” die Zeichenkette ist. Deine ``for``-Schleifen sind so komplett sinnfrei. Die gehen weder über die Zeichenkette noch verwendest Du die Schleife überhaupt, weil die Anweisung im Schleifenkörper völlig unabhängig von der Schleife ist, die also ausser der Anzahl der Wiederholungen keinen Einfluss auf den Programmablauf hat. Und die Schleifen wählst Du immer so das sie genau einmal durchlaufen wird. Womit sie wie gesagt keinen Sinn ergeben.

Die Idee die Zeichenkette mit einer ``for``-Schleife durchzugehen war schon gut, nur musst Du das dann halt auch machen. Also mit *einer* ``for``-Schleife und über die ganze Zeichenkette und nicht über einzelne Buchstaben davon. Beantworte mal an welchen Wert der Name `letter` gebunden wird.
vipeet
User
Beiträge: 6
Registriert: Donnerstag 26. Mai 2016, 08:56

BlackJack hat geschrieben: Beantworte mal an welchen Wert der Name `letter` gebunden wird.
Letter gibt die Anzahl der Buchstaben eines strings aus, soweit ich weiß.
BlackJack

@vipeet: Nein, das ist falsch. Ausgeben tut `letter` schon mal gar nichts, das ist ja ein Name der an einen Wert gebunden wird und keine Funktion oder Anweisung die aktiv etwas tut. Mit welchem Material lernst Du Denn das Du so eine falsche Vorstellung von ``for``-Schleifen hast? Probier das doch einfach mal aus. Lass Dir den Wert von `letter` in einer Schleife über eine ganze Zeichenkette mal ausgeben.
Antworten