{ }codelper
list membershipappendingP0237

What the recipes are missing

You are given the list of ingredients in a fridge and r recipes. The first line gives the number of ingredients m, and the second line gives the m ingredients separated by single spaces. The fridge list may contain the same ingredient more than once. The third line gives r, and each of the next r lines gives one recipe. A recipe line has the dish name, the number of items k, and k items, separated by single spaces. An item is either one ingredient or 2 to 3 ingredients joined with '/' (for example butter/oil). An item with one ingredient is covered if that ingredient is in the fridge list. An item joined with '/' is covered if at least one of its ingredients is in the fridge list. Two ingredients are the same only if their names are entirely equal.
So having egg does not give you eggplant, and having eggplant does not give you egg. For each recipe, print on one line the dish name, the number of uncovered items, and the uncovered items, separated by single spaces. Write the uncovered items exactly as written in the recipe, in the order they first appear in the recipe. If an item with exactly the same characters is written more than once in a recipe, write it once and count it once. butter/oil and oil/butter have different characters, so they are different items. If no item is uncovered, print only the dish name and 0.

Input
1 ≤ m ≤ 300, 1 ≤ r ≤ 300, 1 ≤ k ≤ 30, ingredient and dish names have 1 to 12 lowercase English letters
Output
One line per recipe (dish name, number of uncovered items, those items)
Example 1 · stdin
4
egg milk flour egg
2
pancake 5 egg milk butter/oil sugar butter/oil
omelet 2 egg milk
stdout
pancake 2 butter/oil sugar
omelet 0
Example 2 · stdin
2
eggplant oil
1
fry 4 egg butter/oil egg rice/egg
stdout
fry 2 egg rice/egg
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

Asking whether a list holds a value: Python x in fridge, JS/TS fridge.includes(x), Java fridge.contains(x), C# fridge.Contains(x), C++ std::find(v.begin(), v.end(), x) != v.end(), Craykon fridge.Contains(x).
C has no such function, so you write the loop yourself and compare with strcmp.
This problem asks the question twice.
Once to ask whether the fridge has an ingredient, and once to ask whether an uncovered item has already been written down.
Skip the second one and butter/oil comes out twice.
The first trap is the difference between a list and a string.
If you keep the ingredient line as a string and ask with Python x in line, JS/TS line.includes(x), C# line.Contains(x) or Craykon line.Contains(x), it searches for a substring, and the egg inside eggplant counts as present.
Always ask the split list.
Comparing with strncmp(a, b, strlen(b)) in C also treats words that only share a beginning as equal.
Comparing strings with == in Java checks whether they are the same object, not the same content, so strings made by split come out different even when they are equal.
Use contains / equals.
The second trap is what '/' means.
One of the ingredients is enough, so ask "at least one", as with Python any or JS/TS some.
Asking "all" (all / every) says butter/oil is missing when only oil is there.

Pythonmain.py · 13 lines
m = int(input())fridge = input().split()  # 재료 목록(문자열 그대로가 아니라 낱말의 목록)r = int(input())for _ in range(r):    parts = input().split()    dish, k, items = parts[0], int(parts[1]), parts[2:]    missing = []    for item in items:        # '/'로 이은 재료는 하나라도 목록에 있으면 갖춘 것        have = any(x in fridge for x in item.split("/"))        if not have and item not in missing:  # 같은 항목은 한 번만            missing.append(item)    print(" ".join([dish, str(len(missing))] + missing))
JavaScriptmain.js · 15 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const fridge = lines[1].trim().split(/\s+/); // 재료 배열const r = Number(lines[2]);const out = [];for (let i = 0; i < r; i++) {  const [dish, , ...items] = lines[3 + i].trim().split(/\s+/);  const missing = [];  for (const item of items) {    // 배열의 includes는 같은 낱말을 찾는다. '/'로 이은 것은 하나라도 있으면 된다    const have = item.split("/").some((x) => fridge.includes(x));    if (!have && !missing.includes(item)) missing.push(item);  }  out.push([dish, missing.length, ...missing].join(" "));}console.log(out.join("\n"));
TypeScriptmain.ts · 16 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const fridge: string[] = lines[1].trim().split(/\s+/); // 재료 배열const r: number = Number(lines[2]);const out: string[] = [];for (let i = 0; i < r; i++) {  const [dish, , ...items]: string[] = lines[3 + i].trim().split(/\s+/);  const missing: string[] = [];  for (const item of items) {    // 배열의 includes는 같은 낱말을 찾는다. '/'로 이은 것은 하나라도 있으면 된다    const have: boolean = item.split("/").some((x) => fridge.includes(x));    if (!have && !missing.includes(item)) missing.push(item);  }  out.push([dish, String(missing.length), ...missing].join(" "));}console.log(out.join("\n"));
JavaMain.java · 35 lines
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.Arrays;import java.util.List; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        in.readLine();        List<String> fridge = Arrays.asList(in.readLine().trim().split(" "));        int r = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < r; i++) {            String[] parts = in.readLine().trim().split(" ");            List<String> missing = new ArrayList<>();            for (int j = 2; j < parts.length; j++) {                String item = parts[j];                boolean have = false;                // List.contains는 equals로 비교한다(==는 같은 객체인지를 본다)                for (String x : item.split("/")) {                    if (fridge.contains(x)) {                        have = true;                        break;                    }                }                if (!have && !missing.contains(item)) missing.add(item);            }            out.append(parts[0]).append(' ').append(missing.size());            for (String x : missing) out.append(' ').append(x);            out.append('\n');        }        System.out.print(out);    }}
C#Main.cs · 34 lines
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        Console.ReadLine();        var fridge = new List<string>(Console.ReadLine().Trim().Split(' '));        int r = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        for (int i = 0; i < r; i++)        {            string[] parts = Console.ReadLine().Trim().Split(' ');            var missing = new List<string>();            for (int j = 2; j < parts.Length; j++)            {                string item = parts[j];                // List.Contains는 낱말이 통째로 같은지 본다. string.Contains는 부분 문자열을 찾는다                bool have = false;                foreach (string x in item.Split('/'))                {                    if (fridge.Contains(x)) { have = true; break; }                }                if (!have && !missing.Contains(item)) missing.Add(item);            }            sb.Append(parts[0]).Append(' ').Append(missing.Count);            foreach (string x in missing) sb.Append(' ').Append(x);            sb.Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 36 lines
#include <algorithm>#include <iostream>#include <sstream>#include <string>#include <vector> // 목록에 x와 똑같은 것이 있나(std::find는 ==로 비교하고, std::string의 ==는 내용을 본다)bool contains(const std::vector<std::string> &v, const std::string &x) {    return std::find(v.begin(), v.end(), x) != v.end();} int main() {    int m, r, k;    std::cin >> m;    std::vector<std::string> fridge(m);    for (auto &x : fridge) std::cin >> x;    std::cin >> r;    for (int i = 0; i < r; i++) {        std::string dish, item;        std::cin >> dish >> k;        std::vector<std::string> missing;        for (int j = 0; j < k; j++) {            std::cin >> item;            bool have = false;            std::stringstream ss(item);            std::string x;            while (std::getline(ss, x, '/')) {                if (contains(fridge, x)) { have = true; break; }            }            if (!have && !contains(missing, item)) missing.push_back(item);        }        std::cout << dish << ' ' << missing.size();        for (const auto &x : missing) std::cout << ' ' << x;        std::cout << '\n';    }}
Cmain.c · 49 lines
#include <stdio.h>#include <string.h> static char fridge[300][13];static int m; /* 목록에 같은 재료가 있나: 내용 비교는 strcmp(==는 주소를 비교한다) */int in_fridge(const char *w) {    for (int i = 0; i < m; i++) {        if (strcmp(fridge[i], w) == 0) return 1;    }    return 0;} /* '/'로 이은 재료 가운데 하나라도 있나 */int have_item(const char *item) {    char buf[40];    strcpy(buf, item);    for (char *x = strtok(buf, "/"); x; x = strtok(NULL, "/")) {        if (in_fridge(x)) return 1;    }    return 0;} int main(void) {    int r, k;    char dish[13], items[30][40];    scanf("%d", &m);    for (int i = 0; i < m; i++) scanf("%12s", fridge[i]);    scanf("%d", &r);    for (int i = 0; i < r; i++) {        scanf("%12s %d", dish, &k);        int nmiss = 0;        int miss[30];        for (int j = 0; j < k; j++) {            scanf("%39s", items[j]);            if (have_item(items[j])) continue;            int dup = 0; /* 이미 적은 항목인가 */            for (int t = 0; t < nmiss; t++) {                if (strcmp(items[miss[t]], items[j]) == 0) { dup = 1; break; }            }            if (!dup) miss[nmiss++] = j;        }        printf("%s %d", dish, nmiss);        for (int t = 0; t < nmiss; t++) printf(" %s", items[miss[t]]);        putchar('\n');    }    return 0;}
Craykonmain.cray · 32 lines
Console.ReadLine();fridge = Console.ReadLine().Split(); // 재료 목록r = Console.ReadLine().ToNumber();for (i = 0; i < r; i++){    parts = Console.ReadLine().Split();    missing = [];    for (j = 2; j < parts.Count; j++)    {        item = parts[j];        // 목록의 있나는 같은 낱말을 찾는다. '/'로 이은 것은 하나라도 있으면 된다        have = false;        foreach (x in item.Split("/"))        {            if (fridge.Contains(x))            {                have = true;                break;            }        }        if (!have && !missing.Contains(item))        {            missing.Add(item);        }    }    line = parts[0] + " " + missing.Count;    foreach (x in missing)    {        line += " " + x;    }    Console.WriteLine(line);}