{ }codelper
for-each loopternary operatorbreak / continueP0140

Darts countdown game

Two players start at the same score P and lower their own score by what each dart hits. Player 1 goes first, the players take turns, and each turn has at most three darts. All darts thrown are given on one line, in the order they were thrown. Each dart starts with one of the letters M, S, D and T. M is a miss and scores 0. S, D and T are followed by a number k from 1 to 20 and score k, 2k and 3k points.
k is written without leading zeros. SB scores 25 and DB scores 50 (there is no TB). A dart starting with D (including DB) is called a double. Each time a dart is thrown, its points are subtracted from that player's score. If the result is 0 and the dart is a double, that player wins and the game ends.
The remaining darts are ignored. Otherwise, if the result is less than 2 (it became 0 with a dart that is not a double, or became 1 or negative), the player busts. On a bust the player's score goes back to what it was at the start of this turn, and the turn ends at once.
No darts are left in that turn: the next dart is the other player's first dart. Without a bust the result becomes the new score, and the turn ends if this was the turn's third dart. Each time a turn ends, print the score of the player whose turn it was on its own line. For the winning turn, print 0. If nobody has won and the darts run out before a turn has ended (after its first or second dart), also print a line for that turn with that player's current score. On the last line print the winner's number (1 or 2), or 0 if nobody won. The first line gives P, the second line the number of darts n, and the third line the n darts separated by single spaces.

Input
2 ≤ P ≤ 1,001, 1 ≤ n ≤ 5,000, each dart is M, SB, DB, or S, D or T followed by 1 to 20
Output
one line per turn (the score at the end of that turn), then the winner's number or 0
Example 1 · stdin
101
11
T20 D10 S1 T20 T20 S19 T19 D20 S4 D10 T20
stdout
20
101
20
101
0
1
Example 2 · stdin
60
5
SB M M D20 S5
stdout
35
15
0
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 8 languages

Inside a loop over the darts, you stop and skip by the rules.
On a win, break ignores the remaining darts, and when the turn is not over yet, continue skips printing and switching players (Craykon break;, continue;).
Looping over each item: Python for t in throws, JS and TS for (const t of throws), Java for (String t : throwsList) (throws is a reserved word in Java, so it cannot be a name), C# foreach (string t in throws), C++ for (const std::string& t : throws), Craykon foreach (t in darts).
C has no for-each, so it loops by index and reads each one with scanf.
The multiplier chains ternary operators: C family, JS, TS and Craykon isD ? 2 : isT ? 3 : 1 (it groups from the right, so no parentheses are needed), while Python orders it differently: 2 if isD else 3 if isT else 1.
In Java, C#, C and C++ t.charAt(0) or t[0] is a char, so compare with 'D'; in Python, JS, TS and Craykon it is a one-letter string, so compare with "D".
The most common mistake is undoing only the last dart on a bust.
Remember the score at the start of the turn and go back to it (the first example's second line: 101, not 41).
Other traps are winning on any 0 (only a double can finish), allowing 1 to remain (a double can never clear 1, so it busts), and not counting DB as a double.

Pythonmain.py · 46 lines
import sys data = sys.stdin.read().split()start = int(data[0])n = int(data[1])throws = data[2:2 + n] scores = [start, start]player = 0               # 0이 1번 선수, 1이 2번 선수turn_start = start       # 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)darts = 0                # 이번 차례에 던진 다트 수winner = 0out = [] for t in throws:    if t == "M":        value, is_double = 0, False    else:        ring, num = t[0], t[1:]        base = 25 if num == "B" else int(num)        mult = 2 if ring == "D" else 3 if ring == "T" else 1        value, is_double = base * mult, ring == "D"    darts += 1    left = scores[player] - value     if left == 0 and is_double:          # 더블로 딱 0: 이긴다        scores[player] = 0        winner = player + 1        break                            # 남은 다트는 보지 않는다    if left < 2:                         # 0(더블 아님), 1, 음수: 터짐        scores[player] = turn_start        end_turn = True    else:        scores[player] = left        end_turn = darts == 3    if not end_turn:        continue    out.append(scores[player])    player = 1 - player    turn_start = scores[player]    darts = 0 if winner != 0 or darts > 0:             # 이긴 차례나 다 못 던진 차례도 한 줄    out.append(scores[player])out.append(winner)print("\n".join(map(str, out)))
JavaScriptmain.js · 49 lines
const data = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);const start = Number(data[0]);const n = Number(data[1]);const throws = data.slice(2, 2 + n); const scores = [start, start];let player = 0; // 0이 1번 선수, 1이 2번 선수let turnStart = start; // 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)let darts = 0; // 이번 차례에 던진 다트 수let winner = 0;const out = []; for (const t of throws) {  let value = 0;  let isDouble = false;  if (t !== "M") {    const ring = t[0];    const num = t.slice(1);    const base = num === "B" ? 25 : Number(num);    const mult = ring === "D" ? 2 : ring === "T" ? 3 : 1;    value = base * mult;    isDouble = ring === "D";  }  darts++;  const left = scores[player] - value;   if (left === 0 && isDouble) { // 더블로 딱 0: 이긴다    scores[player] = 0;    winner = player + 1;    break; // 남은 다트는 보지 않는다  }  let endTurn;  if (left < 2) { // 0(더블 아님), 1, 음수: 터짐    scores[player] = turnStart;    endTurn = true;  } else {    scores[player] = left;    endTurn = darts === 3;  }  if (!endTurn) continue;  out.push(scores[player]);  player = 1 - player;  turnStart = scores[player];  darts = 0;} if (winner !== 0 || darts > 0) out.push(scores[player]); // 이긴 차례나 다 못 던진 차례도 한 줄out.push(winner);console.log(out.join("\n"));
TypeScriptmain.ts · 50 lines
import { readFileSync } from "node:fs";const data: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const start: number = Number(data[0]);const n: number = Number(data[1]);const throws: string[] = data.slice(2, 2 + n); const scores: number[] = [start, start];let player = 0; // 0이 1번 선수, 1이 2번 선수let turnStart = start; // 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)let darts = 0; // 이번 차례에 던진 다트 수let winner = 0;const out: number[] = []; for (const t of throws) {  let value = 0;  let isDouble = false;  if (t !== "M") {    const ring = t[0];    const num = t.slice(1);    const base = num === "B" ? 25 : Number(num);    const mult = ring === "D" ? 2 : ring === "T" ? 3 : 1;    value = base * mult;    isDouble = ring === "D";  }  darts++;  const left = scores[player] - value;   if (left === 0 && isDouble) { // 더블로 딱 0: 이긴다    scores[player] = 0;    winner = player + 1;    break; // 남은 다트는 보지 않는다  }  let endTurn: boolean;  if (left < 2) { // 0(더블 아님), 1, 음수: 터짐    scores[player] = turnStart;    endTurn = true;  } else {    scores[player] = left;    endTurn = darts === 3;  }  if (!endTurn) continue;  out.push(scores[player]);  player = 1 - player;  turnStart = scores[player];  darts = 0;} if (winner !== 0 || darts > 0) out.push(scores[player]); // 이긴 차례나 다 못 던진 차례도 한 줄out.push(winner);console.log(out.join("\n"));
JavaMain.java · 57 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int start = Integer.parseInt(br.readLine().trim());        int n = Integer.parseInt(br.readLine().trim());        String[] throwsList = br.readLine().trim().split("\\s+");         int[] scores = {start, start};        int player = 0; // 0이 1번 선수, 1이 2번 선수        int turnStart = start; // 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)        int darts = 0; // 이번 차례에 던진 다트 수        int winner = 0;        StringBuilder out = new StringBuilder();         for (String t : throwsList) {            int value = 0;            boolean isDouble = false;            if (!t.equals("M")) {                char ring = t.charAt(0);                String num = t.substring(1);                int base = num.equals("B") ? 25 : Integer.parseInt(num);                int mult = ring == 'D' ? 2 : ring == 'T' ? 3 : 1;                value = base * mult;                isDouble = ring == 'D';            }            darts++;            int left = scores[player] - value;             if (left == 0 && isDouble) { // 더블로 딱 0: 이긴다                scores[player] = 0;                winner = player + 1;                break; // 남은 다트는 보지 않는다            }            boolean endTurn;            if (left < 2) { // 0(더블 아님), 1, 음수: 터짐                scores[player] = turnStart;                endTurn = true;            } else {                scores[player] = left;                endTurn = darts == 3;            }            if (!endTurn) continue;            out.append(scores[player]).append('\n');            player = 1 - player;            turnStart = scores[player];            darts = 0;        }         if (winner != 0 || darts > 0) out.append(scores[player]).append('\n'); // 이긴 차례나 다 못 던진 차례도 한 줄        out.append(winner).append('\n');        System.out.print(out);    }}
C#Main.cs · 63 lines
using System;using System.Text; class Program{    static void Main()    {        int start = int.Parse(Console.ReadLine().Trim());        int n = int.Parse(Console.ReadLine().Trim());        string[] throws = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);         int[] scores = { start, start };        int player = 0; // 0이 1번 선수, 1이 2번 선수        int turnStart = start; // 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)        int darts = 0; // 이번 차례에 던진 다트 수        int winner = 0;        var sb = new StringBuilder();         foreach (string t in throws)        {            int value = 0;            bool isDouble = false;            if (t != "M")            {                char ring = t[0];                string num = t.Substring(1);                int baseValue = num == "B" ? 25 : int.Parse(num);                int mult = ring == 'D' ? 2 : ring == 'T' ? 3 : 1;                value = baseValue * mult;                isDouble = ring == 'D';            }            darts++;            int left = scores[player] - value;             if (left == 0 && isDouble) // 더블로 딱 0: 이긴다            {                scores[player] = 0;                winner = player + 1;                break; // 남은 다트는 보지 않는다            }            bool endTurn;            if (left < 2) // 0(더블 아님), 1, 음수: 터짐            {                scores[player] = turnStart;                endTurn = true;            }            else            {                scores[player] = left;                endTurn = darts == 3;            }            if (!endTurn) continue;            sb.Append(scores[player]).Append('\n');            player = 1 - player;            turnStart = scores[player];            darts = 0;        }         if (winner != 0 || darts > 0) sb.Append(scores[player]).Append('\n'); // 이긴 차례나 다 못 던진 차례도 한 줄        sb.Append(winner).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 54 lines
#include <array>#include <iostream>#include <string>#include <vector> int main() {    int start, n;    std::cin >> start >> n;    std::vector<std::string> throws(n);    for (auto& t : throws) std::cin >> t;     std::array<int, 2> scores = {start, start};    int player = 0;        // 0이 1번 선수, 1이 2번 선수    int turnStart = start; // 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)    int darts = 0;         // 이번 차례에 던진 다트 수    int winner = 0;     for (const std::string& t : throws) {        int value = 0;        bool isDouble = false;        if (t != "M") {            char ring = t[0];            std::string num = t.substr(1);            int base = num == "B" ? 25 : std::stoi(num);            int mult = ring == 'D' ? 2 : ring == 'T' ? 3 : 1;            value = base * mult;            isDouble = ring == 'D';        }        darts++;        int left = scores[player] - value;         if (left == 0 && isDouble) { // 더블로 딱 0: 이긴다            scores[player] = 0;            winner = player + 1;            break; // 남은 다트는 보지 않는다        }        bool endTurn;        if (left < 2) { // 0(더블 아님), 1, 음수: 터짐            scores[player] = turnStart;            endTurn = true;        } else {            scores[player] = left;            endTurn = darts == 3;        }        if (!endTurn) continue;        std::cout << scores[player] << '\n';        player = 1 - player;        turnStart = scores[player];        darts = 0;    }     if (winner != 0 || darts > 0) std::cout << scores[player] << '\n'; // 이긴 차례나 다 못 던진 차례도 한 줄    std::cout << winner << '\n';}
Cmain.c · 54 lines
#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h> int main(void) {    int start, n;    scanf("%d %d", &start, &n);    int scores[2] = {start, start};    int player = 0;         /* 0이 1번 선수, 1이 2번 선수 */    int turn_start = start; /* 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다) */    int darts = 0;          /* 이번 차례에 던진 다트 수 */    int winner = 0;     /* C에는 for-each가 없다: 다트를 하나씩 읽으며 번호로 돈다 */    for (int i = 0; i < n; i++) {        char t[8];        scanf("%7s", t);        int value = 0;        bool is_double = false;        if (strcmp(t, "M") != 0) {            char ring = t[0];            int base = strcmp(t + 1, "B") == 0 ? 25 : atoi(t + 1);            int mult = ring == 'D' ? 2 : ring == 'T' ? 3 : 1;            value = base * mult;            is_double = ring == 'D';        }        darts++;        int left = scores[player] - value;         if (left == 0 && is_double) { /* 더블로 딱 0: 이긴다 */            scores[player] = 0;            winner = player + 1;            break; /* 남은 다트는 보지 않는다 */        }        bool end_turn;        if (left < 2) { /* 0(더블 아님), 1, 음수: 터짐 */            scores[player] = turn_start;            end_turn = true;        } else {            scores[player] = left;            end_turn = darts == 3;        }        if (!end_turn) continue;        printf("%d\n", scores[player]);        player = 1 - player;        turn_start = scores[player];        darts = 0;    }     if (winner != 0 || darts > 0) printf("%d\n", scores[player]); /* 이긴 차례나 다 못 던진 차례도 한 줄 */    printf("%d\n", winner);    return 0;}
Craykonmain.cray · 58 lines
시작점수 = Console.ReadLine().ToNumber();Console.ReadLine(); // 다트 수 n(목록 개수로 알 수 있다)다트들 = Console.ReadLine().Trim().Split(); 점수 = [시작점수, 시작점수];선수 = 0; // 0이 1번 선수, 1이 2번 선수차례시작 = 시작점수; // 이번 차례를 시작할 때의 점수(터지면 여기로 돌아간다)던진수 = 0; // 이번 차례에 던진 다트 수승자 = 0; foreach (t in 다트들){    값 = 0;    더블 = false;    if (t != "M")    {        고리 = t[0];        수 = t.Substring(1);        기본 = 수 == "B" ? 25 : 수.ToNumber();        배수 = 고리 == "D" ? 2 : 고리 == "T" ? 3 : 1;        값 = 기본 * 배수;        더블 = 고리 == "D";    }    던진수++;    남은 = 점수[선수] - 값;     if (남은 == 0 && 더블)    {        점수[선수] = 0;        승자 = 선수 + 1;        break; // 남은 다트는 보지 않는다    }    차례끝 = false;    if (남은 < 2)    {        점수[선수] = 차례시작;        차례끝 = true;    }    else    {        점수[선수] = 남은;        차례끝 = 던진수 == 3;    }    if (!차례끝)    {        continue;    }    Console.WriteLine(점수[선수]);    선수 = 1 - 선수;    차례시작 = 점수[선수];    던진수 = 0;} if (승자 != 0 || 던진수 > 0){    Console.WriteLine(점수[선수]);}Console.WriteLine(승자);