Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: Python sinterklaasscript  (gelezen 4472 keer)

Offline Mij

  • Lid
Python sinterklaasscript
« Gepost op: 2009/03/18, 16:34:06 »
Ik dacht een script om lootjes te trekken in Python moet zo moeilijk toch niet zijn? Ik heb wel eens wat moeilijkere dingen gedaan. Er gebeurt echter iets vreemds.

import random
oplossing = []
mensen = ["mamma", "pappa", "zus", "broer", "ik"]
keuze = mensen
# 0:(n-2) =^ 1:(n-1)
lengte = len(mensen) - 2

for mens in mensen:
    #Verwijder tijdelijk mens uit keuze
    if mens in keuze:
        keuze.remove(mens)
        reappend = True
    else: reappend = False
    #Kies willekeurig persoon uit lijst
    persoon = keuze[random.randint(0,lengte)]
    #Voeg mens en persoon aan lijst toe
    oplossing.append(mens + ": " + persoon)
    #Voeg mens weer terug in keuze
    if reappend == True:
        keuze.append(mens)
    #Verwijder persoon uit keuze
    keuze.remove(persoon)
        #lengte van keuze wordt 1 minder
    lengte -= 1

for lootje in oplossing:
    print(lootje)
Dit werkt niet goed.
Als ik echter keuze = mensen vervang door keuze = ["mamma", "pappa", "zus", "broer", "ik"] gebeurt komen er foutmeldingen terwijl het in principe precies hetzelfde zou moeten zijn en de = operator bij mijn weten slechts éénmalig is (dus later geen invloed heeft) en niet omkeerbaar (dat mensen ook meteen keuze is). Als ik het als keuze = mensen laat wordt mens alleen mamma, broer, broer of mamma, zus, zus. Dat terwijl er niks in mens veranderd wordt lijkt me.
Ik zit vast!

Offline profoX

  • Lid
    • wesley
    • Lionslink
Re: Python sinterklaasscript
« Reactie #1 Gepost op: 2009/03/18, 17:30:00 »
Wat zou je als output willen?
Human Knowledge Belongs To The World -- Antitrust (2001)
Nederlandstalige Ubuntu documentatie van Ubuntu-NL (wiki)

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: Python sinterklaasscript
« Reactie #2 Gepost op: 2009/03/18, 20:02:57 »
even over dat keuzes = mensen, dit maakt geen kopie van de lijst mensen, maar refereert keuzes, naar dezelfde lijst als die van mensen.

Dus verander remove je een persoon uit keuzes, dan verdwijnt deze ook uit mensen.

gebruikt je: keuzes = mensen[:]
dan wordt er wel een kopie gemaakt en op een andere plek in het geheugen gezet

Hier een script wat ikzelf even in elkaar heb geknutseld. Dacht hetzelfde, "zal wel niet zo moeilijk zijn", maar viel toch meer tegen. Er zit nog een foutje in maar ik heb geen idee hoe dit gemakkelijk op te lossen.

Ik heb trouwens alles in het engels gemaakt,
When writing English, Strunk and White apply.

Python coders from non-English speaking countries: please write
your comments in English, unless you are 120% sure that the code
will never be read by people who don't speak your language.


Ik heb er even een hoop lege regels in gezet zodat, als je het eerst ZELF opnieuw wilt proberen, je niet per ongelijk mijn script leest. Al ik een ander script lees, denk ik meestal "dat had ik ook wel in een paar minuten kunnen doen". Dus vandaar
















#!/usr/bin/env python

import random

def findLinks():
    # Define the persons names
    persons = ["mother", "dad", "sister", "brother", "me"]

    # Copy the list to define the coices
    choices = persons[:]

    # List for saving the combinations
    crosslinks = []
       
    # Let every person take a random name from the choices list
    for person in persons[:]:
        # Check if the last person not only can take his own name
        if len(persons) == 1 and choices[0] == persons[0]:
            return None
       
        # Check if the person not takes his own name
        receiver = None
        while not receiver or receiver == person:
            receiver = random.choice(choices)
       
        # Save the crosslinks and remove the names from the appropiete list
        crosslinks.append([persons.pop(0), choices.pop(choices.index(receiver))])

    return crosslinks

# Run the crosslinking and check if succeeds
links = None
while not links:
    links = findLinks()

# Print each combination
for link in links:
    print "%s has %s" % (link[0], link[1])

Groet,
Een beginnende Python programmeur ;-)

EDIT: script aangepast, zodat het script opnieuw wordt opgestart ipv de foutmelding
« Laatst bewerkt op: 2009/03/19, 19:40:24 door Ronnie »
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: Python sinterklaasscript
« Reactie #3 Gepost op: 2009/03/19, 15:24:44 »
Hoi Ronnie,
Ik zie de volgende regels bij je in het script:
raise "Run the script again, the last person can only choose itself"Dit kun je oplossen door gebruik te maken van functies. Basis:
def functie():
  print('ok')

functie()
Succes ;)

Re: Python sinterklaasscript
« Reactie #4 Gepost op: 2009/03/19, 18:39:23 »
Mij lijkt het dus dat je een lijst hebt met mensen, en die krijgen allemaal iemand toegewezen uit dezelfde lijst, juist? Dus even in C++-pseudocode:

int main() {
    Random rand;
    Vector<String> * mensen = new Vector<String>({"mama","papa","broer","zus","ik"});
    Vector<String> * keuzemogelijk = new Vector<String>(mensen);
    sforeach(String persoon, &mensen) {
        if(keuzemogelijk->size() == 1 && keuzemogelijk->contains(s))
            sthrow(IllegalStateException, "Enkel "+persoon+" schiet over, herstart het programma.");
        while(String keuze = *keuzemogelijk[rand.nextInt(keuzemogelijk->size())] == persoon) {}
        cout << persoon << " kiest " << keuze << endl;
        keuzemogelijk->remove(keuze);
    }
}

Ik ken helaas niet genoeg Python om het direct in Python te schrijven, maar ik hoop dat je het verstaat en dat je er iets aan hebt, het ziet er ongeveer hetzelfde uit als wat Ronnie schrijft, dus...

- SeySayux
I use a Unix-based system, that means I'll get laid as often as I have to reboot.
LibSylph
SeySayux.net

Offline Mij

  • Lid
Re: Python sinterklaasscript
« Reactie #5 Gepost op: 2009/03/20, 13:49:33 »
Ik had al op een wat simpelere manier inderdaad geïmplementeerd dat je soms dezelfde had, door gewoon een willekeurige naam uit de lijst te halen die niet hetzelfde was als de eerste enz (gewoon met een for en while loop). Dan had je op het laatste inderdaad soms dezelfde. Ik wil echter dat het in één keer goed gaat.
In real life kan je dat behalen door enveloppen met namen te maken en dan de lootjes in de enveloppen te doen, te schudden en daarna de lootjes in een andere envelop te doen zodat niemand ooit zichzelf krijgt.

Met de adviezen, zo heb ik het nu werkend:
import random

def verkrijglootjes():
    oplossing = []
    mensen = ["mamma", "pappa", "zus", "broer", "ik"]
    keuze = mensen[:]
    lengte = len(mensen) - 1
    for mens in mensen:
        #Verwijder tijdelijk mens uit keuze
        if mens in keuze:
            keuze.remove(mens)
            reappend = True
            lengte -= 1
        else: reappend = False
        #Kies willekeurig persoon uit lijst
        if lengte >= 0:
            persoon = keuze[random.randint(0,lengte)]
        else: return False
        #Voeg mens en persoon aan lijst toe
        oplossing.append(mens + ": " + persoon)
        #Voeg mens weer terug in keuze
        if reappend == True:
            keuze.append(mens)
        #Verwijder persoon uit keuze
        keuze.remove(persoon)

        lengte = len(keuze) - 1
    return oplossing
sinterklaas = verkrijglootjes()
while sinterklaas is False:
    sinterklaas = verkrijglootjes()
else:
    for lootje in sinterklaas:
        print(lootje)

Alleen dat is verre van ideaal (in theorie bestaat zelfs de mogelijkheid dat het script eindeloos doorgaat).

Offline Mij

  • Lid
Re: Python sinterklaasscript
« Reactie #6 Gepost op: 2009/03/20, 16:57:04 »
Het is gelukt!!


















import random
lootjes = ["mamma", "pappa", "zus", "broer", "ik"]
random.shuffle(lootjes)
lengte = len(lootjes)
for x in range(lengte):
    print(lootjes[x] + " heeft " + lootjes[x-1])
Uiteindelijk veel makkelijker (en korter!) dan eerst gedacht, maar erop komen is zo moeilijk! Ronnie ook bedankt, want daardoor wist ik de shuffle van random weer :), weet nu dat ik variabele[:] moet gebruiken en kreeg ik een nieuw idee. Ik heb voor jou ook maar extra enters toegevoegd voor het geval;)

EDIT: nog een regel geschrapt. EDIT: nog één op suggestie
« Laatst bewerkt op: 2009/03/20, 17:28:32 door Mij »

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: Python sinterklaasscript
« Reactie #7 Gepost op: 2009/03/20, 17:09:27 »
Het is gelukt!!


















import random
lootjes = ["mamma", "pappa", "zus", "broer", "ik"]
random.shuffle(lootjes)
mensen = lootjes[:]
lengte = len(lootjes)
for x in range(lengte):
    lootjes[x] += " heeft " + mensen[x-1]
    print lootjes[x]
Uiteindelijk veel makkelijker (en korter!) dan eerst gedacht, maar erop komen is zo moeilijk! Ronnie ook bedankt, want daardoor wist ik de shuffle van random weer :), weet nu dat ik variabele[:] moet gebruiken en kreeg ik een nieuw idee. Ik heb voor jou ook maar extra enters toegevoegd voor het geval;)

Tja, slim bedacht zo. Op die manier had ik het nog niet bekeken
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline JvH

  • Lid
Re: Python sinterklaasscript
« Reactie #8 Gepost op: 2009/03/20, 17:18:38 »
Dus als ik het goed begrijp is 'lootjes' een geshuffelde lijst personen, en 'mensen' is daar een exacte kopie van.
En je koppelt dan elk item in lootjes aan het voorgaande item in 'mensen'.

Als dit zo is, heb je dan überhaupt 2 arrays nodig? Je kunt dan ook alleen 'mensen' of 'lootjes' gebruiken, toch?

Gaat die loop overigens wel goed? X gaat van 1 tot de lengte van de array. Dan zou ik vermoeden dat bij x = 1 het 0e element wordt opgevraagd...

Offline Mij

  • Lid
Re: Python sinterklaasscript
« Reactie #9 Gepost op: 2009/03/20, 17:22:38 »
Dus als ik het goed begrijp is 'lootjes' een geshuffelde lijst personen, en 'mensen' is daar een exacte kopie van.
En je koppelt dan elk item in lootjes aan het voorgaande item in 'mensen'.

Als dit zo is, heb je dan überhaupt 2 arrays nodig? Je kunt dan ook alleen 'mensen' of 'lootjes' gebruiken, toch?

Gaat die loop overigens wel goed? X gaat van 1 tot de lengte van de array. Dan zou ik vermoeden dat bij x = 1 het 0e element wordt opgevraagd...
welnu, in de lijst is lijst[0] het eerste element. lijst[-1] het een na laatste.

Offline Ronnie

  • Lid
    • ronnie.vd.c
Re: Python sinterklaasscript
« Reactie #10 Gepost op: 2009/03/20, 17:28:02 »
Dus als ik het goed begrijp is 'lootjes' een geshuffelde lijst personen, en 'mensen' is daar een exacte kopie van.
En je koppelt dan elk item in lootjes aan het voorgaande item in 'mensen'.

Als dit zo is, heb je dan überhaupt 2 arrays nodig? Je kunt dan ook alleen 'mensen' of 'lootjes' gebruiken, toch?

Gaat die loop overigens wel goed? X gaat van 1 tot de lengte van de array. Dan zou ik vermoeden dat bij x = 1 het 0e element wordt opgevraagd...
welnu, in de lijst is lijst[0] het eerste element. lijst[-1] het een na laatste.

Met die X zit het wel goed, maar je kunt inderdaad wel een array besparen, de mensen array heb je niet nodig
Ben je ook blij dat Ubuntu zo toegankelijk en gratis is, en wil je graag net als ik iets terugdoen, kijk dan eens rond bij mwanzo, dé poort naar het bijdragen aan Ubuntu en haar gemeenschap!

Documentatie Terminal

Offline JvH

  • Lid
Re: Python sinterklaasscript
« Reactie #11 Gepost op: 2009/03/20, 19:58:29 »
Dus als ik het goed begrijp is 'lootjes' een geshuffelde lijst personen, en 'mensen' is daar een exacte kopie van.
En je koppelt dan elk item in lootjes aan het voorgaande item in 'mensen'.

Als dit zo is, heb je dan überhaupt 2 arrays nodig? Je kunt dan ook alleen 'mensen' of 'lootjes' gebruiken, toch?

Gaat die loop overigens wel goed? X gaat van 1 tot de lengte van de array. Dan zou ik vermoeden dat bij x = 1 het 0e element wordt opgevraagd...
welnu, in de lijst is lijst[0] het eerste element. lijst[-1] het een na laatste.
Ik raak daar zo enorm van in de war... In de ene programmeertaal beginnen ze bij 1 te tellen, de andere bij 0...

Offline Mij

  • Lid
Re: Python sinterklaasscript
« Reactie #12 Gepost op: 2009/03/21, 09:37:33 »
Dus als ik het goed begrijp is 'lootjes' een geshuffelde lijst personen, en 'mensen' is daar een exacte kopie van.
En je koppelt dan elk item in lootjes aan het voorgaande item in 'mensen'.

Als dit zo is, heb je dan überhaupt 2 arrays nodig? Je kunt dan ook alleen 'mensen' of 'lootjes' gebruiken, toch?

Gaat die loop overigens wel goed? X gaat van 1 tot de lengte van de array. Dan zou ik vermoeden dat bij x = 1 het 0e element wordt opgevraagd...
welnu, in de lijst is lijst[0] het eerste element. lijst[-1] het een na laatste.
Ik raak daar zo enorm van in de war... In de ene programmeertaal beginnen ze bij 1 te tellen, de andere bij 0...
Vrijwel alles in Python begint met 0 ook range(n):
>>> for x in range(10):
...     print x
...
0
1
2
3
4
5
6
7
8
9
Het script begint dan ook met de eerste (0) en de laatste (-1) van de lijst.