A second-hand market lists n items, and you answer q search queries in order.
Each item has a name, a kind and a price.
A query "kind maxPrice k" asks for the items of that kind whose price is at most maxPrice. If the kind is *, pick from all items regardless of kind.
For each query, print on one line the number c of picked items, followed by the names of the first k picked items, separated by single spaces.
Picked items are ordered by price, cheapest first; equal prices are ordered by name in dictionary order (character-code order, so digits come before lowercase letters and ab comes before abc).
If c is less than k, print all c names; if c is 0, print just 0.
Prices are given as plain digits without commas, and the output uses plain digits too.
The first line gives n and q, the next n lines give the items as "name kind price", and the following q lines give one query each.
Instead of loops, try a query pipeline: filter → sort → take k → select the names.
Input
1 ≤ n ≤ 1,000, 1 ≤ q ≤ 1,000, 1 ≤ k ≤ 10. Item names are 1–10 lowercase letters or digits and are all different. Kinds are 1–10 lowercase letters (a query's kind may not belong to any item). 1 ≤ price, maxPrice ≤ 1,000,000,000 (integers)
Output
One line per query
Example 1 · stdin
6 4
lamp9 lamp 12000
bluebike bike 85000
redbike bike 85000
kidbike bike 30000
oldlamp lamp 9000
citybike bike 120000
bike 90000 2
lamp 5000 3
* 12000 5
bike 1000000000 10
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 · 6 languages
This problem takes only the languages whose standard tools chain filter, sort, take and select: Python (comprehensions and sorted), JavaScript/TypeScript (array methods), Java (streams), C# (LINQ) and C++ (C++20 std::views). C and Craykon have no list tools that take a function to filter or transform. The same job is Python [it for it in items if ...] → sorted(key=lambda it: (it.price, it.name))[:k], JS/TS filter → sort → slice → map, Java filter → toList() then sorted → limit → map, C# Where → ToList() then OrderBy → ThenBy → Take → Select, and C++ items | std::views::filter(...) collected into a vector, sorted with std::ranges::sort, then std::views::take(k). The trap here is using the filtered result twice, once for the count and once for the names. ① Python filter()/map() return one-shot iterators, so after counting through it, sorted gets nothing. Keep a list with a comprehension or list(...). ② A Java stream can also flow only once: calling count() on a stream variable and then sorted() throws IllegalStateException. Collect with toList() and call stream() again when needed. C# LINQ is the other way round: it is lazy, so using it twice without ToList() raises no error but re-filters from the start each time. ③ In C# OrderBy(...).OrderBy(...), the second OrderBy becomes the new primary key and re-sorts by name (the price would only break ties between equal names, and names are all different). Chain the second key with ThenBy (Java thenComparing). Passing StringComparer.Ordinal makes the name order plainly character-code order. ④ In JS, prices from split are strings, so forgetting Number() turns comparisons into dictionary order where "100" <= "99" is true. TypeScript catches it as a type error when the type says price: number. ⑤ Sorting by price alone leaves equal prices in input order. Give both keys. Also, C++ std::views::filter is a lazy view that cannot be sorted directly (it is not random-access), and JS sort sorts in place, but since filter returns a new array the original list stays as it was.
Pythonmain.py · 22 lines
import sysfrom collections import namedtupleItem = namedtuple("Item", "name kind price")lines = sys.stdin.read().split("\n")n, q = map(int, lines[0].split())items = []for line in lines[1 : n + 1]: name, kind, price = line.split() items.append(Item(name, kind, int(price)))out = []for line in lines[n + 1 : n + 1 + q]: kind, limit, k = line.split() limit, k = int(limit), int(k) # 거르기: 목록 내포는 목록을 만들어 두므로 개수를 센 뒤에도 다시 쓸 수 있다 picked = [it for it in items if (kind == "*" or it.kind == kind) and it.price <= limit] # 정렬 → 앞에서 k개 → 이름만 top = [it.name for it in sorted(picked, key=lambda it: (it.price, it.name))[:k]] out.append(" ".join([str(len(picked))] + top))print("\n".join(out))
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.Comparator;import java.util.List;import java.util.stream.Collectors;public class Main { record Item(String name, String kind, long price) {} public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] first = in.readLine().trim().split(" "); int n = Integer.parseInt(first[0]), q = Integer.parseInt(first[1]); List<Item> items = new ArrayList<>(); for (int i = 0; i < n; i++) { String[] p = in.readLine().trim().split(" "); items.add(new Item(p[0], p[1], Long.parseLong(p[2]))); } Comparator<Item> byPriceThenName = Comparator.comparingLong(Item::price).thenComparing(Item::name); StringBuilder out = new StringBuilder(); for (int i = 0; i < q; i++) { String[] p = in.readLine().trim().split(" "); String kind = p[0]; long limit = Long.parseLong(p[1]); int k = Integer.parseInt(p[2]); // 스트림은 한 번만 흘려보낼 수 있다: 거른 결과를 목록으로 받아 두고 두 번 쓴다 List<Item> picked = items.stream() .filter(it -> (kind.equals("*") || it.kind().equals(kind)) && it.price() <= limit) .toList(); String top = picked.stream() .sorted(byPriceThenName) .limit(k) .map(it -> " " + it.name()) .collect(Collectors.joining()); out.append(picked.size()).append(top).append('\n'); } System.out.print(out); }}
C#Main.cs · 37 lines
using System;using System.Collections.Generic;using System.Linq;using System.Text;record Item(string Name, string Kind, long Price);class Program{ static void Main() { int[] first = Console.ReadLine()!.Trim().Split(' ').Select(int.Parse).ToArray(); int n = first[0], q = first[1]; List<Item> items = Enumerable.Range(0, n) .Select(_ => Console.ReadLine()!.Trim().Split(' ')) .Select(p => new Item(p[0], p[1], long.Parse(p[2]))) .ToList(); var sb = new StringBuilder(); for (int i = 0; i < q; i++) { string[] p = Console.ReadLine()!.Trim().Split(' '); string kind = p[0]; long limit = long.Parse(p[1]); int k = int.Parse(p[2]); List<Item> picked = items .Where(it => (kind == "*" || it.Kind == kind) && it.Price <= limit) .ToList(); // ToList로 한 번 계산해 둔다(그냥 두면 쓸 때마다 다시 거른다) IEnumerable<string> top = picked .OrderBy(it => it.Price) .ThenBy(it => it.Name, StringComparer.Ordinal) // 두 번째 기준은 OrderBy가 아니라 ThenBy .Take(k) .Select(it => it.Name); sb.Append(string.Join(" ", top.Prepend(picked.Count.ToString()))).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 38 lines
#include <algorithm>#include <iostream>#include <ranges>#include <string>#include <tuple>#include <vector>struct Item { std::string name, kind; long long price;};int main() { std::ios::sync_with_stdio(false); int n, q; std::cin >> n >> q; std::vector<Item> items(n); for (auto& it : items) std::cin >> it.name >> it.kind >> it.price; auto byPriceThenName = [](const Item& a, const Item& b) { return std::tie(a.price, a.name) < std::tie(b.price, b.name); }; for (int i = 0; i < q; i++) { std::string kind; long long limit; int k; std::cin >> kind >> limit >> k; // views::filter는 게으른 보기(view)라서 정렬할 수 없다: vector로 받아 둔다 auto view = items | std::views::filter([&](const Item& it) { return (kind == "*" || it.kind == kind) && it.price <= limit; }); std::vector<Item> picked(view.begin(), view.end()); std::ranges::sort(picked, byPriceThenName); std::cout << picked.size(); for (const Item& it : picked | std::views::take(k)) std::cout << ' ' << it.name; std::cout << '\n'; }}