Summe gleichmäßig auf Listenelemente verteilen...

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.
Antworten
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

ich hab' hier 'ne Funktion, die eine Anzahl `space` gleichmäßig auf die Elemente der Liste `cols` verteilen soll, wobei ein eventueller Rest auf die letzten Elemente addiert werden soll:

Code: Alles auswählen

def assign_evenly(cols, space):
    idx = itertools.cycle(range(len(cols)))
    cols = list(reversed(cols))
    while space:
        cols[idx.next()] += 1
        space -= 1
    return list(reversed(cols))

Code: Alles auswählen

>>> assign_evenly([1, 1, 1, 1, 1], 10)
[3, 3, 3, 3, 3]
>>> assign_evenly([1, 1, 1, 1, 1], 11)
[3, 3, 3, 3, 4]
Wie würdet ihr das lösen?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Ich würde das wohl mit Division lösen. ;-)

Edit: Und im Funktionsnamen käme wohl das Wort `distribute` vor.

Edit2: Du vermischt in der Funktiom IMHO auch zu viel. Das erzeugen einer gleichmässigen Verteilung kann man vom Addieren trennen.

Edit3:

Code: Alles auswählen

def generate_even_distribution(bucket_count, item_count):
    value, remainder = divmod(item_count, bucket_count)
    for i in xrange(bucket_count):
        yield value + int(bucket_count - remainder <= i)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack: Das ist ja mal wieder super lässig... :!: Vielen Dank! Wie kommt man auf so was? Ich mein', ich hab' jetzt echt lange mit Deiner Lösung rumgespielt, bis ich das endlich verstanden hab'. Wenn man bedenkt, dass Du mir bereits nach 7 Minuten geantwortet hast... Was braucht man, um sowas zu schreiben?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@mutetella: BlackJacks Ansatz ist in diesem Fall nichts Besonders, das ist der offensichtliche Lösungsweg. Mir würde nicht einmal ein anderer (sinnvoller) Weg einfallen, wie das Problem sonst zu lösen ist.
mutetella hat geschrieben:Was braucht man, um sowas zu schreiben?
Erfahrung.
Das Leben ist wie ein Tennisball.
BlackJack

@mutetella: Wie EyDu schon sagte ist das die offensichtliche Lösung. Erste Idee war Division — wenn ich n Behälter habe und x Objekte darauf verteilen soll, wieviele sind dann am Ende in jedem Behälter? Für die Antwort muss man die Anzahl der Objekte durch die Anzahl der Behälter teilen. Simple Sachaufgabe aus der Schule. Wenn die Rechnung glatt aufgeht, dann hat man die Antwort für jeden Behälter. Ansonsten muss man schauen wie viele Restobjekte man noch verteilen muss, nennen wir den Rest r. Solange man also den `r`-ten Behälter nich nicht erreicht hat, muss man noch ein Objekt mehr in den Behälter tun. Das wäre es dann fast. Du wolltest den Rest ja auf die letzten Behälter verteilen, also muss man für die Bedingung ob noch ein Objekt dazu kommt, nicht ausrechnen bis wann man ein Objekt dazu tun muss, sondern *ab* wann. Und das war's dann auch schon.

Die Erfahrung kommt dann noch ins Spiel das man die `divmod()`-Funktion schon mal gesehen hat, und sich im richtigen Moment an sie erinnert, und der Kniff dass sich die Wahrheitswerte `True` und `False` in die Zahlen 1 und 0 umwandeln lassen. Eigentlich braucht man noch nicht einmal das weil `bool` eine Unterklasse von `int` ist und `True` und `False` tatsächlich auch 1 und 0 sind, man also direkt damit rechnen kann. Ich finde der `int()`-Aufruf macht die Absicht deutlicher und man kann besser erkennen was da passiert, darum habe ich ihn nicht weggelassen.

Man kann das aber auch ohne die beiden Sachen auf diesem Weg lösen. Dann hat man nur ein klein wenig Code mehr.
Antworten