이 페이지는 코딩도장 데이터의 읽기 전용 정적 보관본입니다.

Australian Voting

출처: www.programming-challenges.com

호주식 투표 제도

호주식 투표 제도에서는 투표권자가 모든 후보에 대해 선호도 순으로 순위를 매긴다.

처음에는 1순위로 선택한것만 집계, 한 후보가 50 % 이상 득표시 바로 선출된다. 하지만 50% 이상 득표한 후보가 없으면 가장 적은표를 받은 후보(둘 이상 될 수도)가 우선 탈락된다. 그리고 이렇게 탈락된 후보를 1순위로 찍었던 표를 다시 집계, 아직 탈락되지 않은 후보가운데 가장 높은 선호도를 얻는후보가 그 표를 얻는다. 이런 식으로 가장 약한 후보들을 탈락시키면서 다음 순위의 탈락하지 않은 후보에게 표를 주는 과정을 50% 이상을 얻는 후보가 나오거나 탈락되지 않은 모든 후보가 동률이 될 때까지 반복한다.

입력

첫번째 줄은 후보의 수(n<= 20)를 의미한다. 그 다음으로는 후보의 수만 큼 후보의 이름이 입력된다. 각 후보의 이름은 80글자 이하로 출력가능한 문자로 구성된다. 그 뒤에는 최대 1,000줄이 입력될 수 있는데, 각 줄에는 투표 내역이 입력된다. 각 투표 내역에는 순서대로 1부터 n까지의 수가 입력된다. 첫번째 숫자는 1순위로 찍은 후보의 번호, 두번째 숫자는 2순위로 찍은 후보의 번호, 이런식으로 숫자가 입력된다.

출력

당선된 후보의 이름, 또는 동률을 이룬 후보들의 이름이 들어있는 여러 줄을 출력한다.

Sample Input

3
John Doe
Jane Smith
Jane Austen
1 2 3
2 1 3
2 3 1
1 2 3
3 1 2

위 입력은 총 3명의 후보자가 있고 총 5명의 유권자가 투표를 했음을 나타낸다. 첫번째 유권자는 John Doe를 1순위, Jane Smith를 2순위, Jane Austen을 3순위로 투표한 것이다.

Sample Output

John Doe

2014/03/07 10:43

pahkey

+1 문제에 오해의 소지가 있는 듯 합니다. 예로 두번째 유권자가 투표한 것을(Doe를 1순위로, Smith을 2순위로, Austen을 3순위로) 해석할 수도 있고 (Doe를 2순위로, Smith를 1순위로, Austen을 3순위로) 하고 해석할 수도 있습니다. - Flair Sizz, 2016/04/14 17:19

17개의 풀이가 있습니다.

파이썬 3.4 입니다.

초보이다 보니 기초적인 지식으로 무식하게 풀었습니다.

input을 받은 후에 각 후보 이름이 맨 앞에 들어있는 리스트 형태로 데이터를 변환했습니다. 예제의 경우는 아래와 같습니다.

[['John Doe', 1, 2, 2, 1, 3], ['Jane Smith', 2, 1, 3, 2, 1], ['Jane Austen', 3, 3, 1, 3, 2]]

일순위를 받은 횟수가 전체 투표자중 과반을 넘는지를 확인하고 있으면 당선자로 확정 합니다 (아래 코드의 'decision' 함수). 당선자가 없으면 아래 코드의 'adjust_vote' 함수를 써서 최하점자를 골라내서 제거 대상자 리스트로 옮기고, 남아 있는 후보자의 순위를 조정합니다. 즉, 투표자가 탈락한 후보자를 1등으로 투표했다면 2등은 1등으로, 3등은 2등으로 한단계씩 상승합니다. 만약 투표자가 탈락한 후보자를 2등으로 투표했다면, 1등은 그대로이고, 3등 부터 한단계씩 상승합니다.(문제에는 서술되어있지 않은 부분이지만, 후보자가 아주 많아서 두명 이상이 탈락한 후에 1위가 되는 경우를 생각해 보았습니다.) 이 과정을 거치면 후보자 리스트는 아래 형태가 되네요.

[['John Doe', 1, 2, 1, 1, 2], ['Jane Smith', 2, 1, 2, 2, 1]]

그러면 Doe 씨가 당선 확정이네요

def adjust_vote(candidate_vote,count):
    init_count_length = len(count)
    lowest = min(count)
    removed = []
    for num in count:                   # 최하위를 선정, 후보자 리스트에서 꺼내어 제거자리스트로 옮김     
        if num == lowest:
            pos = count.index(num)          
            temp = candidate_vote.pop(pos)
            count.pop(pos)
            removed.append(temp)
    for x in range(len(removed)):       # 제거자가 꼴지가 아닌 경우 남은 후보자의 순위를 조정
        for y in range (1,len(removed[x])):
            if removed[x][y] != init_count_length:
                for z in range (len(candidate_vote)):
                    if removed[x][y]<candidate_vote[z][y]:
                        candidate_vote[z][y] -= 1
    return candidate_vote

def decision(candidate_vote):    
    elected = ''
    while len(elected) == 0 :                       #당선자가 없는 동안 루프반복
        count = [0] * len(candidate_vote)
        for x in range (len(candidate_vote)):               #각 후보자별로 1위 표 수를 합산
            for y in range (1,len(candidate_vote[x])):
                if candidate_vote[x][y] == 1:
                    count[x] += 1
        for x in range (len(count)):                        # 합산된 1위 표의 수가 과반을 넘는지 판단
            if count[x] >= (len(candidate_vote[x])-1)/2:    #과반을 넘으면 당선자로 선정
                elected = elected + candidate_vote[x][0]            
        else:
            candidate_vote=adjust_vote(candidate_vote,count)    #당선자가 없으면 adjust_vote 함수 실행 
    return elected

candidate_num = int(input())
candidate_vote = []

for x in range (candidate_num):
    temp = []
    temp.append(input())
    candidate_vote.append(temp)

line = input()
while line:
    temp = line.split(" ")
    temp = list(map(int,temp))                    
    for x in range(len(temp)):
        candidate_vote[x].append(temp[x])
    line = input()

print(decision(candidate_vote))    

2014/10/06 22:40

돌구늬ㅋ~썬

C#으로 작성했습니다.

using System.Collections.Generic;
using System.Linq;

        public int FindElected(List<List<int>> inputs, int n)
        {
            var temps = new int[n + 1].ToList();
            foreach (var input in inputs) temps[input.First()]++;
            var outputs = temps.Where(t => t != 0).OrderByDescending(t => t);
            if (outputs.First() > inputs.Count/2)
                return temps.FindIndex(t => t == outputs.First());
            var min = outputs.Last();
            for (int i = 0; i <= n; i++) if (min == temps[i])
                foreach (var input in inputs) if (input.First() == i) input.RemoveAt(0);
            return FindElected(inputs, n);
        }

2015/01/20 20:36

Straß Böhm Jäger

문제 조건 = 풀이법

inputs = STDIN.read.split(/[\r\n]/)
n = inputs[0].to_i
inputs = inputs.drop(1)


names = inputs.take(n)
inputs = inputs.drop(n)

votes = inputs.map {|line| line.split(/\s+/).map(&:to_i) }


counter = {}
loop do
    counter = Hash.new { |hash, key| hash[key] = 0 }
    votes.each do |v|
        counter[v[0]] += 1
    end

    min_votes, max_votes = counter.values.minmax

    if max_votes > votes.length / 2
        puts names[counter.keys.find {|k| counter[k] == max_votes} - 1]
        break
    end

    eliminated = counter.find_all{|k,v| v == min_votes}.map{|k,v| k}    
    eliminated.each do |e|
        votes.each do |v|
            v.delete(e) 
        end     
    end     
end

2014/03/07 17:01

Kim Jaeju

자바입니다. 생각보다 길어졌네요.

package h12_Australian_voting;
import java.util.Scanner;

public class Vote {
    public static void main(String[] args) {
        Count C=new Count();
        Scanner in=new Scanner(System.in);
        System.out.print("후보의 수와, 한줄에 한명씩 후보자 이름을 입력해주세요. (후보 수<=20, 후보 명 글자<=80):");
        int n=in.nextInt(), i,j, vn, win, VN=1000;
        String[] can=new String[n+1]; //can[n]:candidate 후보자이름
        for(i=0;i<n+1;i++){ can[i]=in.nextLine();
            while(can[i].length()>80){
                System.out.println("후보 명은 80글자 이하. 다시입력해주세요");
                can[i]=in.nextLine();
            }
        } //후보자등록. 후보번호:1~n (0은 카운트안함)
        int[] turnout=new int[n+1]; //집계 turnout[후보번호]:후보의 득표수
        do{ 
            for(i=0;i<=n;i++) turnout[i]=0;
            System.out.print("\n후보 "+n+"명, ");
            for(i=1;i<n+1;i++) System.out.print((i)+")"+can[i]+" ");
            System.out.println("\n투표해주세요. 모든 유권자가 투표한 후에는 0을 입력해주세요.(유권자<=1000명) ");
            int[][] vote=new int[VN][n];
            Vote: /*투표실시*/ //유권자번호: 0~vn-1 (vn명)
            for(i=0;i<VN;i++) for(j=0;j<n;j++){
                vote[i][j]=in.nextInt();
                if(vote[i][j]==0) break Vote;
            }
            vn=i+1;
            for(i=0;i<vn;i++) turnout[vote[i][0]]++; /*집계*/

            do{
                C.P(turnout); //집계 과정을 보지 않으려면 이 C.P 출력함수를 삭제하세요.
                win=C.whowin(turnout);
                if(win>0){System.out.println("\nWinner: "+win+")"+can[win]); break;} //50%이상 득표자 1명 당선
                else if(win==-1){ System.out.println("탈락후보 외에 모두 동일득표"); break;}
                else C.drop_recount(turnout, vote);         
            }while(win==0); //win>0:50%이상득표자1명 후보번호, win=0:최다득표자 다수, win=-1:탈락자외 전부동일득표
            System.out.print("\n 다시 투표하시려면 숫자 1을 입력해주세요.(그 외 숫자를 입력하시면 프로그램 종료.)");
        }while(in.nextInt()==1);
    }
}

public class Count {
    int i,j;
    int whowin(int[] t){ //리턴값:50%이상득표자 1명의 후보번호. 0→최다득표자 다수일 경우, -1→탈락자 외 모두 동일득표
        int n=t.length-1, max=0, max_n=0, win=0;
        float h50=(float)n/2;
        for(i=1;i<=n;i++) if(t[i]>max){ max=t[i]; win=i;} //최다득표수 max 구하기
        if(max>h50) return win;
        else if(max==h50){ //t[n+1]={0,50%,50%,0,0,0,...}일 경우→리턴값 -1(탈락자외 모두 동일득표)
            for(i=1;i<=n;i++){
                if(t[i]!=0&&t[i]!=max) break;
                if(t[i]!=0&&t[i]==h50) max_n++;
            } if(max_n>1) win=-1;
            return -1;
        }
        else{   for(i=1;i<=n;i++) if(t[i]!=0 && t[i]!=max) break;
            if(i==n+1) return -1; else return 0;    
        }
    }

    void drop_recount(int[] t, int[][]vote){ //탈락자 가려내고 다시 집계하는 함수
        int min=0, n=t.length-1, vn=vote.length, ii;
        for(i=1;i<=n;i++) if(t[i]!=0){ min=t[i]; break; }
        for(++i;i<=n;i++) if(t[i]!=0 && t[i]<min) min=t[i]; //0이 아닌 최저득표수를 구함

        for(i=1;i<=n;i++) if(t[i]==min) t[i]=0; //최저득표한 후보 득표수를 0으로 처리

        for(i=0;i<vn;i++){
            if(t[vote[i][0]]==0){ //최저득표자(탈락자)에게 첫번째로 투표한 유권자는,
                for(j=1;j<n;j++){
                    if(t[vote[i][j]]!=0){ vote[i][0]=vote[i][j]; t[vote[i][0]]++; break;}
                }   //남아있는 후보들 중 그 유권자가 가장 큰 선호도를 보이는 후보를 알아내서,
            }           //그 유권자의 첫번째 투표후보를 그 후보로 처리하고, 그 후보의 득표율을 1 증가시킨다.
        }
    }

    void P(int[] t){ //Count 과정 출력함수
        int n=t.length-1; System.out.print("\n Count: ");
        for(i=1;i<=n;i++){
            System.out.print(i+")"+((t[i]==0)?"_":t[i])+" ");
        }
    }
}

2014/03/10 16:33

Katherine

python.

import operator 

def elect(n, votes):
    counter = [0] * n
    for vote in votes:
        counter[vote[0]-1] += 1

    total = sum(counter)
    max_index, max_value = max(enumerate(counter), key=operator.itemgetter(1))
    min_index, min_value = min(enumerate(counter), key=operator.itemgetter(1))

    if max_value == min_value:
        print "No elected"
    elif max_value * 1.0 / total >= 0.5:
        print "candidate %d elected" % (max_index+1)
    else:
        for vote in votes:
            if vote[0]-1 == min_index:
                vote.pop(0)
        elect(n, votes)


def get_votes(data):
    votes = []
    for line in data.split("\n"):
        line = line.strip()
        if not line: continue
        votes.append(map(int, line.split()))
    return votes


elect(3, get_votes("""
1 2 3
2 1 3
2 3 1
1 2 3
3 1 2
"""))

2014/05/02 16:57

pahkey

import sys
num = input()
names = [raw_input() for i in range(num)]
votes =[]
while 1:
    v = raw_input()
    if not v : break
    votes.append(map(int,v.split()))
votes_num = len(votes)

minimum = [v[0] for v in votes].count(1) #가장 적은득표수
while 1:
    for i in range(num):
        n = [v[0] for v in votes].count(i)
        if n*2 > num:
            print names[i-1] #당선자 이름 출력
            sys.exit()
        if n<minimum : minimum = n ; omit =  i #가장 적은 득표수 갱신, 탈락자 갱신
    for i in range(num):
        if len(votes[i]) == 1 : # 더이상 탈락시킬 사람이 없는데 과반득표가 안나온건 동률
            print 'same votes'
            sys.exit()
    for i in range(num):
        if votes[i][0]==omit : votes[i].pop(0) #탈락자 제거

2016/01/25 15:35

상파

class end(BaseException):
    def __init__(self):pass
class candidate:
    def __init__(self, name):
        self.name = name
        self.papers = []
    def get(self, li):
        self.papers += li
    def give(self):
        return self.papers
    def append(self, paper):
        self.papers.append(paper)
def cal(li, rank = 0, excepted_list = []):
    result = [0] * len(li[0])
    for x in li:
        for i in range(len(li[0])):
            if x.index(i) in excepted_list:
                continue
            else:
                result[x.index(i)]+=i
                break
    target = list(reversed(sorted(result)))[rank]
    canList = []; index = 0
    while result.count(target)>0:
        canList.append(result.index(target)+index)
        result.pop(result.index(target))
        index += 1
    return canList, target

if __name__ == '__main__':
    num_of_candidate = int(input('>>>'))
    candidate_list = []; papers = []
    for i in range(num_of_candidate):
        candidate_list.append(candidate(input()))
    print('type \'end\' to escape')
    while 1:
        inpt = input('>>>')
        if inpt == 'end':break
        inpt = list(int(x)-1 for x in inpt.split())
        if len(inpt) != num_of_candidate:
            print('Wrong input.')
        else:
            papers.append(inpt)
            index = inpt.index(min(inpt))
            candidate_list[index].append(inpt)
    len_of_paper = []
    for candidate in candidate_list:
        len_of_paper.append(len(candidate.give()))
    if max(len_of_paper)/len(papers) > 0.5:
        print(candidate_list[len_of_paper.index(max(len_of_paper))].name)
    else:
        excepted_candidates = []
        excepted_nums = []
        while 1:
            p = []
            for candidate in list(x for x in candidate_list if x not in excepted_candidates):
                p.append(len(candidate.give()))
            p = min(p)
            gots = []
            for i, candidate in enumerate(candidate_list):
                if len(candidate.give()) == p:
                    excepted_candidates.append(candidate)
                    excepted_nums.append(i)
                    gots += candidate.give()
            alive = list(x for x in candidate_list if x not in excepted_candidates)
            if gots:
                target = cal(gots, rank = 0, excepted_list = excepted_nums)
                if len(target[0])>1 and len(alive)>1:
                    print("Error: two or more candidates at exchanging")
                    break
                else:
                    candidate_list[target[0][0]].get(gots)
            if list(len(x.give()) for x in alive) == [len(alive[0].give())]*len(alive) and len(alive)>1:
                print('two or more candidates left')
                break
            try:
                for candidate in alive:
                    if len(candidate.give()) > len(papers)/2:
                        print(candidate.name)
                        raise end
            except end:
                break

순위를 중요도로 생각해서 결과가 반대로 나와서 헷갈렸네요;; 파이썬 3.5.1

2016/04/14 17:01

Flair Sizz

Ruby

def elect(names,votes) 
  counter = votes.reduce(Hash.new(0)) {|cnt,prefer| cnt[prefer.first] +=1; cnt }
  min_votes, max_votes = counter.values.minmax
  if max_votes >= votes.size / 2
    names[counter.key(max_votes)-1] 
  else 
    last_places = counter.select {|_,v| v == min_votes}.keys
    votes.each {|v| v.delete_if {|prefer| last_places.include? prefer} }
    elect(names, votes)
  end
end

n, inputs = gets.to_i, STDIN.read.split(/[\r\n]/)
names, votes = inputs.shift(n), inputs.map {|vote| vote.split.map &:to_i }
p elect(names, votes)  #=> "John Doe

Test

names = [["John Doe", "Jane Smith", "Jane Austen"]
votes = [[1, 2, 3], [2, 1, 3], [2, 3, 1], [1, 2, 3], [3, 1, 2]]]
expect(elect(names,votes)).to eq "John Doe"

2016/04/16 09:18

rk

John Doe

Jane Smith

#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#define MAX_COLS 100000
int main() {
    FILE* f = fopen("input.txt","r");
    char s[MAX_COLS];
    int n = 0;
    int index = 0;
    char **name;
    int *vote;
    while(NULL!=fgets(s, MAX_COLS, f)) {
        if(!index) {
            n = s[0]-48;
            name = (char**) malloc (sizeof(char*) * n+1);
            for(int i = 0 ; i<=n; i++)
                name[i] = (char*) malloc (sizeof(char) * 20);

            vote = (int*) malloc (sizeof(int) * n);
            for(int i = 0 ; i<n; i++)
                vote[i] = 0;
        } 
        else if(index <= n) {
            strcpy(name[index], s);
        } else {
            int j = 0;
            for(int i = 0 ; i<n; i++) {
                vote[i] = vote[i] + s[j]-48;
                j+=2;
            }
        }
        index++;
    }
    int min = 100;
    for(int i = 0 ; i<n; i++) {
        if(min > vote[i]) 
            min = vote[i];
    }

    for(int i = 0 ; i<n; i++) {
        if(min == vote[i])
            printf("%s\n", name[i+1]);
    }
    return 0;
}

2016/11/23 13:19

코딩초보

def chk_del(n_list,t_list,num):
    tmp = [x,count(len(n_list)) for x in range(len(n_list))]
    _max = max(tmp)
    result = list()
    while True:
        if _max in tmp:
            result.append(n_list[tmp.index(_max)])
            n_list.pop(tmp.index(_max))
        else:
            break
    return result

def chk_1st(n_list,t_list):
    for x in range(len(names)):
        if c_list[x].count(1) / len(names) >= 0.5:
            return [names[x],x]
    return False

names = [input() for x in range(int(input()))]
r_list = [list(map(int,input().split(' '))) for x in range(11)]
c_list = [[r_list[y][x] for y in range(len(r_list))] for x in range(len(names))]
while True:
    chk,x = chk_1st(names,c_list)
    if chk == False:
        c_list[x] += [1 for z in range(c_list[names.index(y)].count(1)) for y in chk_del(names,c_list,x)]
    else:
        print(chk)
        break

#### 2017.02.03 D-384 ####

응망진창 그냥 뭐랄까 빨리겜하고싶다!!(진짜 겜하고싶은건아닙니다.) 그런쫒기는마음으로 생각나는데로 코딩했는데 그냥 잘되서 올려여 허허헣

2017/02/03 23:28

GunBang

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class AustralianVoting {

    public static void main(String[] args) throws FileNotFoundException {
        String path = AustralianVoting.class.getResource("").getPath();
        Scanner sc = new Scanner(new File(path + "/AustralianVoting.txt"));

        int n = Integer.valueOf(sc.nextLine());
        String[] v = new String[n];
        List<Stack<Integer>> nn = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            v[i] = sc.nextLine();
        }

        int k = 0;
        while (sc.hasNextLine()) {
            Stack<Integer> stack = new Stack<>();
            for (int i = 0; i < n; i++) {
                stack.add(sc.nextInt());
            }
            nn.add(stack);
            k++;
        }

        int l = nn.size();

        for (int i = 0; i < n; i++) {
            List<Integer> list = new ArrayList<>();
            for (int j = 0; j < l; j++) {
                list.add(nn.get(j).get(0));
            }
            Map<Integer, Long> map = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
            Optional<Map.Entry<Integer, Long>> max = map.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue));

            Long maxVotedCount = max.get().getValue();

            if (maxVotedCount >= ((float) k / 2)) {
                map.entrySet().stream().forEach(m -> {
                    if (m.getValue().equals(maxVotedCount)) {
                        System.out.println(v[m.getKey() - 1]);
                    }
                });
                break;
            }

            Optional<Map.Entry<Integer, Long>> min = map.entrySet().stream().min(Comparator.comparing(Map.Entry::getValue));
            Integer minVoted = min.get().getKey();
            nn.stream().forEach(e -> {
                if (e.get(0).equals(minVoted)) e.remove(0);
            });
        }
    }
}

2017/05/11 23:25

genius.choi

s1=input()
s1=int(s1)
name=[]
for i in range(s1):
    naming=input()
    name.append(naming)


cnt=[0,0,0]
vote=[[1,2,3],[2,1,3],[2,3,1],[1,3,2],[3,1,2]]
per50=round((len(vote)+0.1)/2)

for i in range(len(vote)):
    j=0
    if vote[i][j]== 1:
        cnt[0]=cnt[0]+1
    elif vote[i][j]== 2:
        cnt[1]=cnt[1]+1
    elif vote[i][j]== 3:
        cnt[2]=cnt[2]+1
maxcnt=0
mincnt=0
for i in range(len(cnt)):
    if cnt[i]>cnt[maxcnt]:
        maxcnt=i
    if cnt[i]<cnt[mincnt]:
        mincnt=i

    if cnt[maxcnt]<per50:
        for i in range(len(vote)):
            j=0
            if vote[i][j]==cnt[mincnt]:
                for i in range(len(vote)):
                    j=1
                    if vote[i][j]== 1:
                        cnt[0]=cnt[0]+1
                    elif vote[i][j]== 2:
                        cnt[1]=cnt[1]+1
                    elif vote[i][j]== 3:
                        cnt[2]=cnt[2]+1
print("max",name[maxcnt])

2017/07/16 23:34

나후승

Python3

여러가지로 시도해 봤는데 결국 클래스 만드는 게 제일 깔끔하네요.

class Candidate:
    cnt = 0
    def __init__(self, name):
        self.name = name
        Candidate.cnt += 1
        self.number = Candidate.cnt
        self.score = 0

    def __lt__(self, other):
        return self.score < other.score

data = '3\nJohn Doe\nJane Smith\nJane Austen\n1 2 3\n2 1 3\n2 3 1\n1 2 3\n3 1 2'
data = data.split('\n')
N = int(data[0])
cands = {Candidate(name) for name in data[1:N+1]}
votes = [[int(y) for y in x.split()] for x in data[N+1:]]

while len(cands) > 1:    
    for c in cands:  # 집계
        c.score = [v[0] for v in votes].count(c.number)
        if c.score >= 50 + (N is 2): 
            print(c.name); exit()  # 당선

    minvotes, maxvotes = min(cands).score, max(cands).score
    if minvotes == maxvotes: break  # 전부 동률    
    loosers = {c for c in cands if c.score == minvotes}  # 탈락자
    cands = cands - loosers    
    votes = [v if v[0] not in [c.number for c in loosers] else v[1:] for v in votes] # 다음 순위 득표

print([c.name for c in cands])

2017/08/01 06:04

Noname

def aust_vote(candi,counting):
    fail = []
    tmp = [[i[0] for i in counting].count(j+1) for j in range(len(candi))]

    maxc, minc = max(tmp), min(tmp)
    if maxc >= len(counting)/2:
        if tmp.count(maxc) == 1: return candi[tmp.index(maxc)]
        else:
            return candi[tmp.index(maxc)], candi[tmp[tmp.index(maxc)+1:].index(maxc)+tmp.index(maxc)+1]
    else:
        fail = [i+1 for i in range(len(tmp)) if tmp[i] == minc]
        for i in counting:
            if i[0] in fail: i.pop(0)

    return aust_vote(candi,counting)


candidate,counting = [],[]
n = int(input('후보자 수: '))
for i in range(n): candidate.append(input('후보: '))
print('투표 내역 입력')
while 1:
    counting.append(list(map(int,input().split())))
    if counting[-1] == [] : del counting[-1]; break

print(f'당선자: {aust_vote(candidate,counting)}')

2018/07/14 03:28

Creator

import re
def inp() : # 후보 수, 이름, 선호도를 사용자 입력으로 받음
    N = int(input("후보 수 : "))
    cand = [input("NAME {}: ".format(na+1)) for na in range(N)]
    pre_com, PRE_mat, co = re.compile("\d+"), [], 1
    while True :
        PRE_mat.append(list(map(int, pre_com.findall(input("INPUT {} : ".format(co))))))
        co += 1
        if (PRE_mat[-1]) == [] : break
    return N, cand, PRE_mat[:-1]

def First_c(np, ns, prem) :
    counter = [0]*np
    for itera in prem :
        counter[itera.index(min(itera))] += 1
    return counter

def filt(nu_before, ca_before, mat_before, counter_before) : # 최소 카운트 키록한 후보 제외한 테이블 반환
    num_min, collection_min = counter_before.count(min(counter_before)), set([]) # 최소 카운트 기록한 후보의 수, 후보의 인덱스
    for w in range(0, len(counter_before)) : # 삭제 후보의 인덱스를 집합 collection_min에 추가
        if counter_before[w] == min(counter_before) : collection_min.add(w)
    for r in range(0, len(mat_before)) :
        if mat_before[r].index(min(mat_before[r])) != counter_before.index(max(counter_before)) : # 최대 득표자 선택이 아닌 경우
            while mat_before[r].index(min(mat_before[r])) in collection_min : # 해당 행의 최소값을 얻은 후보가 삭제 대상이 아닐 떄 까지, 해당 행의 값을 계속 갱신
                mat_before[r] = list(map(lambda x : x-1, (mat_before[r])))
                mat_before[r][mat_before[r].index(min(mat_before[r]))] += nu_before

    for t in range(0, len(counter_before)) : # nu_before, ca_before 갱신
        if counter_before[t] == min(counter_before) :
            ca_before[t] = '#'
            nu_before -= 1
    return nu_before, ca_before, mat_before


def m_proced() :
    n, CAND, pre_MAT = inp() # 사용자 입력
    while True :
        loc_res = First_c(n, CAND, pre_MAT) # local result의 최대값이 오직 하나 존재하고 과반수일 떄 : break, 결과 return
        if loc_res.count(max(loc_res)) == 1 and max(loc_res) >= (len(pre_MAT)/2) :
            return CAND[loc_res.index(max(loc_res))]
        else : # 종료 조건 만족하지 않을 떄 :
            n, CAND, pre_MAT = filt(n, CAND, pre_MAT, loc_res)

print(m_proced())

결과

후보 수 : 3
NAME 1: John Doe
NAME 2: Jane Smith
NAME 3: Jane Austen
INPUT 1 : 1 2 3
INPUT 2 : 2 1 3
INPUT 3 : 2 3 1
INPUT 4 : 1 2 3
INPUT 5 : 3 1 2
INPUT 6 : 
John Doe

2020/01/15 17:28

GG

def vote_res(vote, elCandidate):
    res = {}
    maxV = 0
    for v in vote:
        for n in v:
            if n not in elCandidate:
                if n not in res:
                    res[n]=0
                res[n] += 1
                maxV = max(maxV, res[n])
                break
    return res, maxV

def winner(maxV, res):
    minV = maxV
    wCandidate = []
    for k in res:
        if res[k]==maxV:
            wCandidate.append(k)
        else:
            minV = min(minV, res[k])
    return wCandidate, minV

inp = """3
John Doe
Jane Smith
Jane Austen
1 2 3
2 1 3
2 3 1
1 2 3
3 1 2"""

inp_split = inp.split('\n')
#print(inp_split)
N = int(inp_split[0])
candidate = {}
vote = []
for i in range(N):
    candidate[i+1] = inp_split[i+1]
idx = N+1
while idx< len(inp_split):
    vote.append(inp_split[idx].split())
    idx += 1

elCandidate = []
winCandidate = []
while len(winCandidate) != 1:
    res = {}
    maxV = 0
    minV = N    
    res, maxV = vote_res(vote, elCandidate)
    winCandidate, minV = winner(maxV, res)
    for k in res:
        if res[k]==minV:
            elCandidate.append(k)
print(candidate[int(winCandidate[0])])

2024/01/17 13:30

insperChoi

JAVA입니다.

package question3.Australian_voting;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) throws FileNotFoundException, IOException {
        //입력값 처리
        BufferedReader br = new BufferedReader
                (new FileReader(Main.class.getResource("input.txt").getPath()));

        int candNum = Integer.parseInt(br.readLine());
        Candidate[] candidates = new Candidate[candNum];

        for (int i = 0; i < candNum; i++) {
            candidates[i] = new Candidate(br.readLine());
        }

        int voterNum = 0;

        while(true) {
            String line = br.readLine();
            if(line == null) {
                break;
            }
            Voter voter = new Voter(line.split(" "));
            candidates[voter.getCand()].supporters.add(voter);
            voterNum++;
        }

        br.close();
        //입력값 처리 끝

        while(true) {
            List<Candidate> highestCands = new ArrayList<Candidate>();
            int highestVote = 0;
            List<Candidate> lowestCands = new ArrayList<Candidate>();
            int lowestVote = voterNum;
            /*최다 득표한 후보자는 조건 판정에 사용, 최소 득표한 후보자는 terminated 처리하고 해당 후보자를
             * 지지하는 투표자는 다음 후보자로 넘김
             */

            for (Candidate candidate : candidates) {
                if(candidate.terminated) {
                    continue;
                }

                if(candidate.supporters.size() == highestVote) {
                    highestCands.add(candidate);
                }
                else if (candidate.supporters.size() > highestVote) {
                    highestVote = candidate.supporters.size();
                    highestCands = new ArrayList<Candidate>();
                    highestCands.add(candidate);
                }

                if(candidate.supporters.size() == lowestVote) {
                    lowestCands.add(candidate);
                }
                else if (candidate.supporters.size() < lowestVote) {
                    lowestVote = candidate.supporters.size();
                    lowestCands = new ArrayList<Candidate>();
                    lowestCands.add(candidate);
                }
            }

            if(highestCands.size() == candNum || //동률이거나
                    (highestCands.size() == 1 && highestVote >= voterNum/2)) {
                //50% 이상의 표를 얻은 경우
                for (Candidate candidate : highestCands) {
                    System.out.println(candidate.name);
                }
                break;
            }

            //조건이 충족되지 않은 경우
            for (Candidate candidate : lowestCands) {
                candidate.terminated = true;
            }
            for (Candidate candidate : lowestCands) {
                for (Voter supporter : candidate.supporters) {
                    while(true) {
                        supporter.prefIndex++;
                        Candidate nextCand = candidates[supporter.getCand()];
                        if(nextCand.terminated) {
                            continue;
                        }
                        nextCand.supporters.add(supporter);
                        break;
                        //다음 후보자도 terminated 되었을 수 있으므로 그렇지 않은 후보자를 찾을 때까지 반복
                    }
                }
            }
        }
    }

}

package question3.Australian_voting;

public class Voter {
    int[] prefOrder;
    int prefIndex;

    public Voter(String[] prefOrderStr) {
        prefOrder = new int[prefOrderStr.length];

        for (int i = 0; i < prefOrderStr.length; i++) {
            prefOrder[i] = Integer.parseInt(prefOrderStr[i]);
        }

        prefIndex = 0;
    }

    int getCand() {
        //현재 지목한 후보자의 배열에서의 인덱스를 반환
        return prefOrder[prefIndex] - 1;
    }

}

package question3.Australian_voting;

import java.util.ArrayList;
import java.util.List;

public class Candidate {
    String name;
    List<Voter> supporters;
    boolean terminated;

    public Candidate(String name) {
        this.name = name;
        this.supporters = new ArrayList<Voter>();
        this.terminated = false;
    }
}

2025/02/13 21:31

박준우

목록으로