• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Niespodziewane zachowanie funkcji własnej

VPS Starter Arubacloud
0 głosów
239 wizyt
pytanie zadane 31 października 2018 w Python przez El Lirón Obywatel (1,350 p.)
edycja 31 października 2018 przez El Lirón

Cześć! Piszę kalkulator wyborczy, czyli program do rozdzielania mandatów dla partii w zależności ile mają głosów. Stworzyłem funkcję give_the_seat(), która powinna: 1) posortować listę "wygrywających ilorazów" (win_list), 2) wybrać największy iloraz (the_b) 3) sprawdzić, czy na liście ilorazów każdej partii znajduje się największy iloraz i jeśli tak, to przydzielić tej partii miejsce w Sejmie/Radzie (funkcja get_seat()). Następnie w części głównej usunąć największy iloraz z listy i powtarzać operację tak długo, jak długo są mandaty do rozdania.

Problem polega na tym, że wszystkie partie otrzymują... tą samą ilość miejsc równą liczbie miejsc do wygrania. Co tu jest nie tak? Czy ja gdzieś pomyliłem kolejność, przeoczyłem coś? Czy cała ta funkcja jest zła? Będę wdzięczny za każdą podpowiedź.

kod główny:
 


import P

#user gives info about electoral district

hm_seats=int(input("Ile mandatów jest możliwych do zdobycia w tym okręgu? "))

hm_parties=int(input("Ile partii wzięło udział w wyborach w tym okręgu? "))

party_list=[]

x=0
while x < hm_parties:
    p=P.Party()
    party_list.append(p)
    x += 1

system = int(input("""
W jakim systemie zostaną przeliczone głosy?
d'Hondta - wybierz 1
Sainte-Lague - wybierz 2
Hare'a-Niemayera - wybierz 3 
"""))

scope=[1, 2, 3]
while system not in scope:
    system = int(input("""
Wybierz 1, 2 lub 3
d'Hondta - wybierz 1
Sainte-Lague - wybierz 2
Hare'a-Niemayera - wybierz 3 
"""))

# calculations in d'Hondt system
## creatig quotients' lists for each party

if system == 1:
    for p in party_list:
        divisor = 1

        x=0
        while x < hm_seats:
            quotient = p.votes/divisor
            p.quotients_list.append(quotient)
            divisor += 1
            x += 1

## creating list of all qoutients

    all_quotients = []

    for p in party_list:
        for quotient in p.quotients_list:
            all_quotients.append(quotient)

## looking for biggests quotients

    winning_quotients = []

    x=0
    while x < hm_seats:
        the_biggest = P.find_the_biggest(all_quotients)
        x+=1
        winning_quotients.append(the_biggest)
        all_quotients.sort(key=int, reverse=True)
        all_quotients.pop(0)

    print("test0: ", winning_quotients)
## distrubution of seats

    x=hm_seats
    while x>0:
        P.give_the_seat(party_list, p.quotients_list, winning_quotients)
        winning_quotients.sort(key=int, reverse=True)
        winning_quotients.pop(0)
        x-=1

    print("test1: ", party_list[0].seats)
    print("test2: ", party_list[1].seats)
    print("test3: ", party_list[2].seats)

Funkcje i klasy:
 


class Party(object):
    def __init__(self):
        self.ask_party_name()
        self.ask_party_votes()
        self.seats = 0
        self.quotients_list = []

    def ask_party_name(self):
        self.party_name = input("Podaj nazwę lub skrót partii: ")

    def ask_party_votes(self):
        self.votes = int(input("Podaj liczbę głosów, którą zdobyła partia " + self.party_name + ": "))

    def get_seat(self):
        self.seats += 1

def find_the_biggest(list):
    list.sort(key=int, reverse=True)
    the_b = list[0]
    return the_b

def give_the_seat(par_list, q_list, win_list):
    win_list.sort(key=int, reverse=True)
    the_b = win_list[0]
    for p in par_list:
        for q in q_list:
            if q == the_b:
                p.get_seat()

Output:

Ile mandatów jest możliwych do zdobycia w tym okręgu? 7
Ile partii wzięło udział w wyborach w tym okręgu? 3
Podaj nazwę lub skrót partii: A
Podaj liczbę głosów, którą zdobyła partia A: 100
Podaj nazwę lub skrót partii: B
Podaj liczbę głosów, którą zdobyła partia B: 200
Podaj nazwę lub skrót partii: C
Podaj liczbę głosów, którą zdobyła partia C: 400

W jakim systemie zostaną przeliczone głosy?
d'Hondta - wybierz 1
Sainte-Lague - wybierz 2
Hare'a-Niemayera - wybierz 3
1
test0:  [400.0, 200.0, 200.0, 133.33333333333334, 100.0, 100.0, 100.0]
test1:  7
test2:  7
test3:  7

Process finished with exit code 0

informacje o metodzie d'Hondt'a jeśli ktoś chce przeczytać :)
https://pl.wikipedia.org/wiki/Metoda_D%E2%80%99Hondta

1
komentarz 31 października 2018 przez adrian17 Ekspert (349,420 p.)
Wrzucisz cały kod?
komentarz 31 października 2018 przez El Lirón Obywatel (1,350 p.)
Jasne, już wrzucam. Zaraz edytuję pytanie.

1 odpowiedź

+1 głos
odpowiedź 31 października 2018 przez adrian17 Ekspert (349,420 p.)

Na oko... to nie ma sensu.

while x>0:
        give_the_seat(party_list, p.quotients_list, winning_quotients)

Przekazujesz jako argument listę współczynników jednej konkretnej partii i zawsze z nią porównujesz.

BTW, dużo kodu masz przekombinowane. Na przykład:

the_biggest = find_the_biggest(all_quotients)

to po prostu

the_biggest = max(all_quotients)

Podobnie, cała ta pętla

    x=0
    while x < hm_seats:
        the_biggest = find_the_biggest(all_quotients)
        x+=1
        winning_quotients.append(the_biggest)
        all_quotients.sort(key=int, reverse=True)
        all_quotients.pop(0)

To po prostu

    all_quotients.sort(reverse=True)
    winning_quotients = all_quotients[:hm_seats]

 

komentarz 31 października 2018 przez El Lirón Obywatel (1,350 p.)
1) Masz rację. Już zmieniłem te parametry i sprawdzę jak to działa.

2) Bardzo ciekawe, nie znałem tego :)

Dzięki za pomoc.

Podobne pytania

0 głosów
1 odpowiedź 236 wizyt
0 głosów
1 odpowiedź 130 wizyt
0 głosów
1 odpowiedź 158 wizyt

93,008 zapytań

141,975 odpowiedzi

321,256 komentarzy

62,350 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...