{ }codelper
逆順ループ入れ子の条件真偽値P0127

自動販売機のおつり

自動販売機が客におつりを出す。
硬貨は 10 ウォン、50 ウォン、100 ウォン、500 ウォンの四種類である。
一行目に自動販売機に入っている 10 ウォン、50 ウォン、100 ウォン、500 ウォン硬貨の枚数がこの順に与えられる。
二行目に客の数 q が与えられ、続く q 行に客ごとの商品の値段 p と入れたお金 m が与えられる。
客が入れたお金は別に集められるので、おつりには使わない。
客を順に処理し、客ごとに一行を出力せよ。
m が p より小さければ "金額不足" を出力する。
そうでなければ、おつり c = m - p を 500 ウォン、100 ウォン、50 ウォン、10 ウォンの順に合わせる。
硬貨ごとに、残りの金額を超えず、自動販売機に残っている枚数を超えない範囲でできるだけ多く使う。
これで c がちょうど合えば、500 ウォン、100 ウォン、50 ウォン、10 ウォン硬貨を何枚使ったかをこの順に空白一つで区切って出力し、使った硬貨を自動販売機から引く。
c が 0 なら "0 0 0 0" になる。
こうして c がちょうど合わなければ "おつりなし" を出力し、自動販売機の硬貨はそのままにする。

入力
硬貨の枚数はそれぞれ 0 以上 1000 以下、1 ≤ q ≤ 100、10 ≤ p ≤ 10000、0 ≤ m ≤ 50000、p と m は 10 の倍数
出力
客ごとに一行:硬貨の枚数四つ、"金額不足"、または "おつりなし"
例 1 · stdin
5 2 3 1
5
120 1000
430 500
290 300
600 500
1000 1000
stdout
1 3 1 3
0 0 1 2
おつりなし
金額不足
0 0 0 0
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

入力は小さい硬貨から、計算と出力は大きい硬貨からです。
なので配列を後ろから前へ回ります:Python range(3, -1, -1)(終わりの -1 は含まれないので 0 まで回る)、C 系・JS・TS for (i = 3; i >= 0; i--)、Craykon 繰り返す (i = 3; i >= 0; i--)。
小さい硬貨から回ると、10 ウォンをたくさん出す誤った答えになります。
使う枚数は min(残り金額 / 硬貨, 残り枚数) です。
整数の商は Python //、JS・TS Math.floor(a / b)、Craykon 数学.商(a, b) で、Java・C#・C・C++ は int どうしの / がそのまま商です。
残り枚数を忘れたり、数えながら自動販売機から引いてしまい、失敗した客のときにも硬貨が消えたりするのがよくある間違いです。
まず計算だけして、ok = left == 0 という真偽値で成功を確かめてから引きます。
真偽値の型は Python bool(True/False)、Java boolean、C# bool、C++ bool、C は <stdbool.h> の bool(C23 からはヘッダー不要)、JS・TS boolean、Craykon 真/偽 です。
10・50・100・500 ウォンは小さい硬貨が大きい硬貨を割り切るので、大きいほうから使うこの方法で合わせられる金額を取りこぼしません。

Pythonmain.py · 21 行
COINS = [10, 50, 100, 500]stock = list(map(int, input().split()))q = int(input())for _ in range(q):    p, m = map(int, input().split())    if m < p:        print("金額不足")    else:        left = m - p        used = [0, 0, 0, 0]        # 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로        for i in range(3, -1, -1):            used[i] = min(left // COINS[i], stock[i])            left -= used[i] * COINS[i]        ok = left == 0        if ok:            for i in range(4):                stock[i] -= used[i]            print(used[3], used[2], used[1], used[0])        else:            print("おつりなし")  # 자판기 동전은 건드리지 않았다
JavaScriptmain.js · 27 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const COINS = [10, 50, 100, 500];const stock = lines[0].trim().split(/\s+/).map(Number);const q = Number(lines[1]);const out = [];for (let t = 0; t < q; t++) {  const [p, m] = lines[2 + t].trim().split(/\s+/).map(Number);  if (m < p) {    out.push("金額不足");  } else {    let left = m - p;    const used = [0, 0, 0, 0];    // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로    for (let i = 3; i >= 0; i--) {      used[i] = Math.min(Math.floor(left / COINS[i]), stock[i]);      left -= used[i] * COINS[i];    }    const ok = left === 0;    if (ok) {      for (let i = 0; i < 4; i++) stock[i] -= used[i];      out.push([used[3], used[2], used[1], used[0]].join(" "));    } else {      out.push("おつりなし"); // 자판기 동전은 건드리지 않았다    }  }}console.log(out.join("\n"));
TypeScriptmain.ts · 28 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const COINS: number[] = [10, 50, 100, 500];const stock: number[] = lines[0].trim().split(/\s+/).map(Number);const q: number = Number(lines[1]);const out: string[] = [];for (let t = 0; t < q; t++) {  const [p, m] = lines[2 + t].trim().split(/\s+/).map(Number);  if (m < p) {    out.push("金額不足");  } else {    let left: number = m - p;    const used: number[] = [0, 0, 0, 0];    // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로    for (let i = 3; i >= 0; i--) {      used[i] = Math.min(Math.floor(left / COINS[i]), stock[i]);      left -= used[i] * COINS[i];    }    const ok: boolean = left === 0;    if (ok) {      for (let i = 0; i < 4; i++) stock[i] -= used[i];      out.push([used[3], used[2], used[1], used[0]].join(" "));    } else {      out.push("おつりなし"); // 자판기 동전은 건드리지 않았다    }  }}console.log(out.join("\n"));
JavaMain.java · 36 行
import java.util.Scanner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int[] coins = {10, 50, 100, 500};        int[] stock = new int[4];        for (int i = 0; i < 4; i++) stock[i] = sc.nextInt();        int q = sc.nextInt();        StringBuilder out = new StringBuilder();        for (int t = 0; t < q; t++) {            int p = sc.nextInt();            int m = sc.nextInt();            if (m < p) {                out.append("金額不足\n");            } else {                int left = m - p;                int[] used = new int[4];                // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로                for (int i = 3; i >= 0; i--) {                    used[i] = Math.min(left / coins[i], stock[i]);                    left -= used[i] * coins[i];                }                boolean ok = left == 0;                if (ok) {                    for (int i = 0; i < 4; i++) stock[i] -= used[i];                    out.append(used[3]).append(' ').append(used[2]).append(' ')                       .append(used[1]).append(' ').append(used[0]).append('\n');                } else {                    out.append("おつりなし\n"); // 자판기 동전은 건드리지 않았다                }            }        }        System.out.print(out);    }}
C#Main.cs · 42 行
using System;using System.Linq; class Program{    static void Main()    {        int[] coins = { 10, 50, 100, 500 };        int[] stock = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        int q = int.Parse(Console.ReadLine());        for (int t = 0; t < q; t++)        {            int[] pm = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();            int p = pm[0], m = pm[1];            if (m < p)            {                Console.WriteLine("金額不足");            }            else            {                int left = m - p;                int[] used = new int[4];                // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로                for (int i = 3; i >= 0; i--)                {                    used[i] = Math.Min(left / coins[i], stock[i]);                    left -= used[i] * coins[i];                }                bool ok = left == 0;                if (ok)                {                    for (int i = 0; i < 4; i++) stock[i] -= used[i];                    Console.WriteLine($"{used[3]} {used[2]} {used[1]} {used[0]}");                }                else                {                    Console.WriteLine("おつりなし"); // 자판기 동전은 건드리지 않았다                }            }        }    }}
C++main.cpp · 33 行
#include <algorithm>#include <array>#include <iostream> int main() {    const std::array<int, 4> coins = {10, 50, 100, 500};    std::array<int, 4> stock;    for (int& s : stock) std::cin >> s;    int q;    std::cin >> q;    for (int t = 0; t < q; t++) {        int p, m;        std::cin >> p >> m;        if (m < p) {            std::cout << "金額不足\n";        } else {            int left = m - p;            std::array<int, 4> used{};            // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로            for (int i = 3; i >= 0; i--) {                used[i] = std::min(left / coins[i], stock[i]);                left -= used[i] * coins[i];            }            bool ok = left == 0;            if (ok) {                for (int i = 0; i < 4; i++) stock[i] -= used[i];                std::cout << used[3] << ' ' << used[2] << ' ' << used[1] << ' ' << used[0] << '\n';            } else {                std::cout << "おつりなし\n"; // 자판기 동전은 건드리지 않았다            }        }    }}
Cmain.c · 34 行
#include <stdbool.h>#include <stdio.h> int main(void) {    const int coins[4] = {10, 50, 100, 500};    int stock[4];    for (int i = 0; i < 4; i++) scanf("%d", &stock[i]);    int q;    scanf("%d", &q);    for (int t = 0; t < q; t++) {        int p, m;        scanf("%d %d", &p, &m);        if (m < p) {            puts("金額不足");        } else {            int left = m - p;            int used[4] = {0};            // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로            for (int i = 3; i >= 0; i--) {                int can = left / coins[i];                used[i] = can < stock[i] ? can : stock[i];                left -= used[i] * coins[i];            }            bool ok = left == 0;            if (ok) {                for (int i = 0; i < 4; i++) stock[i] -= used[i];                printf("%d %d %d %d\n", used[3], used[2], used[1], used[0]);            } else {                puts("おつりなし"); // 자판기 동전은 건드리지 않았다            }        }    }    return 0;}
Craykonmain.cray · 37 行
COINS = [10, 50, 100, 500];stock = コンソール.数読み();q = コンソール.行読み().数に();繰り返す (t = 0; t < q; t++){    pm = コンソール.数読み();    p = pm[0];    m = pm[1];    もし (m < p)    {        コンソール.書く("金額不足");    }    でなければ    {        left = m - p;        used = [0, 0, 0, 0];        // 큰 동전부터: 자리 3(500원)에서 0(10원)으로 거꾸로        繰り返す (i = 3; i >= 0; i--)        {            used[i] = 数学.小さい方(数学.商(left, COINS[i]), stock[i]);            left -= used[i] * COINS[i];        }        ok = left == 0;        もし (ok)        {            繰り返す (i = 0; i < 4; i++)            {                stock[i] -= used[i];            }            コンソール.書く([used[3], used[2], used[1], used[0]]);        }        でなければ        {            コンソール.書く("おつりなし"); // 자판기 동전은 건드리지 않았다        }    }}