Seite 2 von 2

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 13:59
von BlackJack
@garreth: ``lambda`` ist überflüssig wenn es bloss eine Funktion mit den selben Argumenten aufruft die es selbst bekommen hat.

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 14:01
von sparrow
Hi Garreth,

deine beiden Lösungen verhalten sich anders als das was der Threadstarter gepostet hat.

[codebox=python file=x]alle = [20,33,21,32,27,7,25,16,32,27,21,22,44,55,12, -1, 2]

def original(alle):
result = []
for i in (alle):
if i >0 and i<4:
result.append(1)
if i >3 and i<7:
result.append(2)
if i >6 and i<10:
result.append(3)
if i >9 and i<13:
result.append(4)
if i >12 and i<16:
result.append(5)
if i >15 and i<19:
result.append(6)
if i >18 and i<22:
result.append(7)
if i >21 and i<25:
result.append(8)
if i >24 and i<28:
result.append(9)
if i >27 and i<31:
result.append(10)
if i >30 and i<34:
result.append(11)
elif i>33:
result.append(12)
return result


def gareth1(alle):
from math import ceil
alle = list(map(lambda x: ceil(x/3), alle))
return alle


def gareth2(alle):
def transform_number(i):
result = i / 3
if result < i//3+0.5 and i % 3 != 0:
result += 1
return round(result)
return list(map(lambda x: transform_number(x), alle))[/code]

Code: Alles auswählen

>>> alle
[20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
>>> original(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
>>> gareth1(alle)
[6.0, 11.0, 7.0, 10.0, 9.0, 2.0, 8.0, 5.0, 10.0, 9.0, 7.0, 7.0, 14.0, 18.0, 4.0, -1.0, 0.0]
>>> gareth2(alle)
[7.0, 11.0, 7.0, 11.0, 9.0, 3.0, 9.0, 6.0, 11.0, 9.0, 7.0, 8.0, 15.0, 19.0, 4.0, 0.0, 1.0]

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 14:30
von garreth
sparrow hat geschrieben:Hi Garreth,

deine beiden Lösungen verhalten sich anders als das was der Threadstarter gepostet hat.
Manchmal vergesse ich zu erwähnen, dass ich ausschließlich Python 3 programmiere. Der Fehler tritt nur in Python 2 auf und muss natürlich in diesem Fall angepasst werden.

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 14:35
von sparrow
Die Sonderfälle werden auch unter Python3 nicht berücksichtigt:

Code: Alles auswählen

# python3 -i test.py
>>> alle
[20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
>>> original(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
>>> gareth1(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 15, 19, 4, 0, 1]
>>> gareth2(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 15, 19, 4, 0, 1]

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 15:01
von snafu
Unter der Annahme, dass n ganzzahlig ist:

Code: Alles auswählen

[(min(n, 33) + 3) // 3 for n in numbers if n > 0]
EDIT: Den funktional orientierten Lösungen entnehme ich meinen Denkfehler, dass nur 2 addiert werden darf. Sonst liefern alle Vielfachen von 3 das falsche Ergebnis.

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 15:12
von garreth
sparrow hat geschrieben:Die Sonderfälle werden auch unter Python3 nicht berücksichtigt:
So nun speziell für sparrow unter Berücksichtigung der Sonderfälle, lauffähig unter Python 2 und mit anschaulicher Darstellung einer if-elif-else Abfrage:

Code: Alles auswählen

def transform_number(i):
    if i < 1:
        return False
    elif i > 33:
        return 12
    else:
        result = i / 3.0
        if result == i / 3.0+0.5 and i % 3 != 0:
            result += 1
        return int(round(result))

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    print(alle)
    alle = list(filter(None,map(transform_number,alle)))
    print(alle)
Danke an blackjack für den Hinweis.

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 15:25
von snafu
haeuslermartin hat geschrieben:Die Zahll der ursprünglichen Listeneinträge bleibt bei 12, im Endeffekt soll immer nur ein neuer Eintrag hinzukommen, dafür fällt der letzte aber raus.

Code: Alles auswählen

from collections import deque

numbers = ((min(n, 33) + 2) // 3 for n in all_numbers if n > 0)
result = deque(numbers, 12)
print(list(result))

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 15:26
von Hyperion
@garreth: Den Code hast Du doch nie laufen lassen‽ Da ist ein Syntaxfehler in Zeile 8...

Code: Alles auswählen

if result = i / 3.0+0.5 and i % 3 != 0:
Abgesehen davon empfinde ich diese Berechnung als unelegant. Und wie man das anschaulicher und vermutlich auch effizienter berechnet ist ja nun schon gezeigt worden. Und eine Mischung aus Integer- und booleschen Rückgabewerten empfinde ich auch als wenig gelungen. Da sollte man die Filterung vor verlagern, wie es bei den Lösungen mit List Comprehensions auch gemacht worden ist.

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 16:33
von garreth
Hyperion hat geschrieben:@garreth: Den Code hast Du doch nie laufen lassen‽ Da ist ein Syntaxfehler in Zeile 8...
Abgesehen davon empfinde ich diese Berechnung als unelegant. Und wie man das anschaulicher und vermutlich auch effizienter berechnet ist ja nun schon gezeigt worden. Und eine Mischung aus Integer- und booleschen Rückgabewerten empfinde ich auch als wenig gelungen. Da sollte man die Filterung vor verlagern, wie es bei den Lösungen mit List Comprehensions auch gemacht worden ist.
Nein und ja, ich habe ihn schon mal laufen lassen, allerdings noch mal hier abgetippt. Der Fehler hat sich dann eingeschlichen.
Du hast Recht, die Berechnung ist unelegant deswegen nochmal ein neuer Versuch:

Code: Alles auswählen

def transform_number(i):
    if i < 1:
        return 0
    elif i > 33:
        return 12
    else:
        if i % 3 == 0:
            return int(i/3)
        else:   
            return int(i/3+1)

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    print(alle)
    alle = list(filter(None,map(transform_number, alle)))
    print(alle)

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 17:04
von snafu
Dein neuer Code ist leider wieder falsch. Im Original soll bei einer 3 eine 1 ausgeliefert werden. Bei dir würde bei einer 3 (oder einer 6 oder einer 9 ...) eine 0 (bzw 1 bzw 2 ...) rauskommen. Erkennst du den Fehler? ;)

Du musst im Grunde gar nicht unterscheiden, ob bei einer Division durch 3 ein Rest rauskommt, sondern du musst die Zahl nur so "vorbereiten", dass die ganzzahlige Division das gewünschte Ergebnis liefert. Das kann man ja im Kopf mal anhand einiger Beispiele durchrechnen.

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 17:21
von Hyperion
Und vor allem könntest Du Dir einen simplen Test schreiben, der das Vergleichen gegenüber der Erwartunsgmenge übernimmt:

Code: Alles auswählen

if __name__ == '__main__':
    erwartet = [7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    print(alle)
    ergebnis = list(filter(None,map(transform_number, alle)))
    print(ergebnis)
    assert(erwartet == ergebnis )
(ich weiß jetzt nicht, ob ich das richtige ``result`` kopiert habe!)

Eigentlich würde man sich dafür einen richtigen Unit Test schreiben, aber für den Anfang und dieses kleine Snippet geht's auch so - auf jeden Fall ist das besser, als gar nicht zu testen! :-)

Re: neue Liste

Verfasst: Dienstag 10. Februar 2015, 17:49
von garreth
snafu hat geschrieben:Dein neuer Code ist leider wieder falsch. Im Original soll bei einer 3 eine 1 ausgeliefert werden. Bei dir würde bei einer 3 (oder einer 6 oder einer 9 ...) eine 0 (bzw 1 bzw 2 ...) rauskommen. Erkennst du den Fehler? ;)

Du musst im Grunde gar nicht unterscheiden, ob bei einer Division durch 3 ein Rest rauskommt, sondern du musst die Zahl nur so "vorbereiten", dass die ganzzahlige Division das gewünschte Ergebnis liefert. Das kann man ja im Kopf mal anhand einiger Beispiele durchrechnen.
Diesen Fehler kann ich grad nicht reproduzieren. Ich hab das mal mit den beanstandeten Zahlen versucht Ausgabe ist sowohl in Python 2 als auch Python3 wie vorgesehen.

Aber ich hab mir das mal kurz durch den Kopf gehen lassen. Theoretisch könnte man dies auch so lösen:

Code: Alles auswählen

def transform_number(i):
    if i < 1:
        return 0
    elif i > 33:
        return 12
    else:
        return int((i-0.1)/3+1)

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    erwartet = [7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
    print(alle)
    alle = list(filter(None,map(transform_number, alle)))
    print(alle)
    print(alle == erwartet)
Würde allerdings nur mit Ganzzahlen funktionieren und die -0.1 ist magisch und meiner Meinung nach schlecht verständlich.

Danke an Hyperion für den Tip mit dem erwartet Vergleich, macht die Angelegenheit wesentlich einfacher!

Re: neue Liste

Verfasst: Mittwoch 11. Februar 2015, 09:39
von Hyperion
garreth hat geschrieben: Danke an Hyperion für den Tip mit dem erwartet Vergleich, macht die Angelegenheit wesentlich einfacher!
Danke mir vor allem für den Hinweis auf Unit Testing! Befasse Dich damit ruhig, auch wenn das außerhalb des eigentlichen Problems hier steht :-)

Re: neue Liste

Verfasst: Mittwoch 11. Februar 2015, 19:52
von garreth
Hyperion hat geschrieben:Danke mir vor allem für den Hinweis auf Unit Testing! Befasse Dich damit ruhig, auch wenn das außerhalb des eigentlichen Problems hier steht :-)
Auf jeden Fall, danke dir. Hatte das gestern rausgemacht, weil ich keine Ausgabe hatte. Heute konnte ich mich dann kurz einlesen und ja, wertvoller Tip!