Picking the restaurant that disappoints no one much
A meeting place is chosen from a table of ratings that n friends gave to m restaurants.
The j-th value on the r-th line is the rating friend r gave to restaurant j.
A rating is an integer, and a cell where the friend has not been there and gave no rating holds x.
For each restaurant, find the lowest (min) and the highest (max) of the ratings it received. x is not counted.
A restaurant that received no rating at all is never chosen.
Choose the restaurant whose min is the highest.
If several restaurants share that min, choose the one among them with the highest max, and if that is also equal, the one with the smallest number.
Then count the friends who like the chosen restaurant best.
Count a friend who rated the chosen restaurant and whose rating for it equals the highest of all ratings that friend gave (the friend counts even if several restaurants got that highest rating).
The first line gives n and m separated by a single space.
Each of the next n lines gives m values separated by single spaces.
On the first line print the number of the chosen restaurant, its min and its max separated by single spaces, and on the second line print the number of friends who like it best.
If no restaurant received any rating, print only one line with 0.
Input
1 ≤ n ≤ 200. 1 ≤ m ≤ 200. Each value is x or an integer from −100 to 100
Output
First line: restaurant number, min, max. Second line: number of friends. If no restaurant can be chosen, one line with 0
Example 1 · stdin
3 4
5 3 x 4
2 3 x 4
x 3 x -1
stdout
2 3 3
1
Example 2 · stdin
2 2
x x
x x
stdout
0
main.py
Error List00F8 ↓ · ⇧F8 ↑
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
The smallest and largest values come in one call with Python min(col)/max(col), JS/TS Math.min(...col)/Math.max(...col), C# col.Min()/col.Max(), C++ std::minmax_element; C, Java and Craykon compare one by one in a loop, as in Mathf.Min(lo, v). Trap 1: what happens with no values differs by language. Python min([]) stops with ValueError, but JS Math.min() returns Infinity and Math.max() returns -Infinity. So if you do not skip a restaurant without ratings, in JS that restaurant wins with a min of Infinity (the first example prints 3 Infinity -Infinity). Check first whether the collected list is empty. Trap 2: when you use a loop, do not start from 0. If the ratings are only −5 and −3, the max becomes 0, and if they are only 5 and 3, the min becomes 0. Start from C INT_MAX/INT_MIN or Java Integer.MAX_VALUE/Integer.MIN_VALUE, or from the first rating you meet, as the Craykon solution does. Trap 3: if you compare the values you read without converting them to numbers, the order is string order and "9" is greater than "10". Trap 4: the comparison that breaks a tie in min by max is done in order from the first value by Python tuples, (lo, hi) > (best_lo, best_hi), and by > on a C++ std::pair. C# tuples have no >, so write key.CompareTo(bestKey) > 0. In JS/TS, [lo, hi] > [bestLo, bestHi] turns the arrays into the strings "9,9" and "10,10" and compares those, which is wrong. Spell it out: lo > bestLo || (lo === bestLo && hi > bestHi). Comparing only the min and leaving out the max is wrong too. Trap 5: going from the smallest number and replacing with > keeps the smaller number on a tie. With >= the later restaurant takes over. Trap 6: x must be left out of a friend's highest rating too. In Python, max(row) on a list that contains None is a TypeError. For a C# int?[], row.Max() leaves the nulls out. Craykon keeps a cell without a value as null and filters with v == null (passing null to Mathf.Max stops the program). A friend who did not rate the chosen restaurant is not counted.
Pythonmain.py · 32 lines
import sysdef main(): data = sys.stdin.read().split() n, m = int(data[0]), int(data[1]) # 별점이 없는 칸은 None으로 둔다 grid = [[None if tok == "x" else int(tok) for tok in data[2 + r * m:2 + (r + 1) * m]] for r in range(n)] best = 0 # 고른 식당 번호(0이면 아직 없음) best_key = None for j in range(m): col = [row[j] for row in grid if row[j] is not None] if not col: # min([])은 ValueError다: 별점이 없는 식당은 건너뛴다 continue key = (min(col), max(col)) # 튜플은 앞의 값부터 차례로 견준다 if best == 0 or key > best_key: # >라서 같으면 번호가 작은 식당이 남는다 best, best_key = j + 1, key if best == 0: print(0) return fans = 0 for row in grid: mine = row[best - 1] if mine is not None and mine == max(v for v in row if v is not None): fans += 1 print(best, best_key[0], best_key[1]) print(fans)main()
JavaScriptmain.js · 35 lines
const tokens = require("fs").readFileSync(0, "utf8").split(/\s+/).filter((s) => s !== "");const n = Number(tokens[0]);const m = Number(tokens[1]);// 별점이 없는 칸은 null로 둔다. 문자열인 채로 견주면 "9" > "10"이라 수로 바꾼다const grid = [];for (let r = 0; r < n; r++) { grid.push(tokens.slice(2 + r * m, 2 + (r + 1) * m).map((t) => (t === "x" ? null : Number(t))));}let best = 0; // 고른 식당 번호(0이면 아직 없음)let bestLo = 0;let bestHi = 0;for (let j = 0; j < m; j++) { const col = grid.map((row) => row[j]).filter((v) => v !== null); if (col.length === 0) continue; // Math.min()은 Infinity다: 별점이 없는 식당은 건너뛴다 const lo = Math.min(...col); const hi = Math.max(...col); // 배열끼리 >로 견주면 문자열로 바뀌므로 값을 하나씩 견준다 if (best === 0 || lo > bestLo || (lo === bestLo && hi > bestHi)) { best = j + 1; bestLo = lo; bestHi = hi; }}if (best === 0) { console.log(0);} else { let fans = 0; for (const row of grid) { const mine = row[best - 1]; if (mine !== null && mine === Math.max(...row.filter((v) => v !== null))) fans++; } console.log(best + " " + bestLo + " " + bestHi + "\n" + fans);}
TypeScriptmain.ts · 38 lines
import { readFileSync } from "node:fs";const tokens: string[] = readFileSync(0, "utf8").split(/\s+/).filter((s) => s !== "");const n: number = Number(tokens[0]);const m: number = Number(tokens[1]);// 별점이 없는 칸은 null로 둔다. 문자열인 채로 견주면 "9" > "10"이라 수로 바꾼다const grid: (number | null)[][] = [];for (let r = 0; r < n; r++) { grid.push(tokens.slice(2 + r * m, 2 + (r + 1) * m).map((t) => (t === "x" ? null : Number(t))));}const rated = (v: number | null): v is number => v !== null;let best = 0; // 고른 식당 번호(0이면 아직 없음)let bestLo = 0;let bestHi = 0;for (let j = 0; j < m; j++) { const col: number[] = grid.map((row) => row[j]).filter(rated); if (col.length === 0) continue; // Math.min()은 Infinity다: 별점이 없는 식당은 건너뛴다 const lo: number = Math.min(...col); const hi: number = Math.max(...col); // 배열끼리 >로 견주면 문자열로 바뀌므로 값을 하나씩 견준다 if (best === 0 || lo > bestLo || (lo === bestLo && hi > bestHi)) { best = j + 1; bestLo = lo; bestHi = hi; }}if (best === 0) { console.log(0);} else { let fans = 0; for (const row of grid) { const mine = row[best - 1]; if (mine !== null && mine === Math.max(...row.filter(rated))) fans++; } console.log(best + " " + bestLo + " " + bestHi + "\n" + fans);}
JavaMain.java · 54 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer;public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); int n = Integer.parseInt(st.nextToken()), m = Integer.parseInt(st.nextToken()); Integer[][] grid = new Integer[n][m]; // 별점이 없는 칸은 null for (int r = 0; r < n; r++) { st = new StringTokenizer(in.readLine()); for (int j = 0; j < m; j++) { String tok = st.nextToken(); grid[r][j] = tok.equals("x") ? null : Integer.valueOf(tok); } } int best = 0, bestLo = 0, bestHi = 0; // best가 0이면 아직 고른 식당이 없다 for (int j = 0; j < m; j++) { // 0이 아니라 가장 큰 값·가장 작은 값에서 시작해야 음수 별점도 맞게 나온다 int lo = Integer.MAX_VALUE, hi = Integer.MIN_VALUE, count = 0; for (int r = 0; r < n; r++) { if (grid[r][j] == null) continue; lo = Math.min(lo, grid[r][j]); hi = Math.max(hi, grid[r][j]); count++; } if (count == 0) continue; // 별점이 없는 식당은 건너뛴다 if (best == 0 || lo > bestLo || (lo == bestLo && hi > bestHi)) { best = j + 1; bestLo = lo; bestHi = hi; } } if (best == 0) { System.out.println(0); return; } int fans = 0; for (int r = 0; r < n; r++) { if (grid[r][best - 1] == null) continue; int top = Integer.MIN_VALUE; for (int j = 0; j < m; j++) { if (grid[r][j] != null) top = Math.max(top, grid[r][j]); } if (grid[r][best - 1] == top) fans++; } System.out.println(best + " " + bestLo + " " + bestHi); System.out.println(fans); }}
C#Main.cs · 47 lines
using System;using System.Linq;class Program{ static void Main() { string[] head = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int n = int.Parse(head[0]), m = int.Parse(head[1]); var grid = new int?[n][]; // 별점이 없는 칸은 null for (int r = 0; r < n; r++) { grid[r] = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries) .Select(tok => tok == "x" ? (int?)null : int.Parse(tok)).ToArray(); } int best = 0; // 고른 식당 번호(0이면 아직 없음) (int lo, int hi) bestKey = (0, 0); for (int j = 0; j < m; j++) { int[] col = grid.Where(row => row[j] != null).Select(row => row[j].Value).ToArray(); if (col.Length == 0) continue; // 빈 배열의 Min()은 예외다: 별점이 없는 식당은 건너뛴다 var key = (col.Min(), col.Max()); // 튜플에는 > 연산자가 없어서 CompareTo로 앞의 값부터 견준다 if (best == 0 || key.CompareTo(bestKey) > 0) { best = j + 1; bestKey = key; } } if (best == 0) { Console.WriteLine(0); return; } int fans = 0; foreach (int?[] row in grid) { int? mine = row[best - 1]; // int?의 Max()는 null을 빼고 구한다 if (mine != null && mine == row.Max()) fans++; } Console.WriteLine($"{best} {bestKey.lo} {bestKey.hi}"); Console.WriteLine(fans); }}
C++main.cpp · 53 lines
#include <algorithm>#include <iostream>#include <optional>#include <string>#include <utility>#include <vector>int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m; std::cin >> n >> m; // 별점이 없는 칸은 std::nullopt std::vector<std::vector<std::optional<int>>> grid(n, std::vector<std::optional<int>>(m)); for (auto& row : grid) { for (auto& cell : row) { std::string tok; std::cin >> tok; if (tok != "x") cell = std::stoi(tok); } } int best = 0; // 고른 식당 번호(0이면 아직 없음) std::pair<int, int> bestKey; for (int j = 0; j < m; j++) { std::vector<int> col; for (const auto& row : grid) { if (row[j]) col.push_back(*row[j]); } if (col.empty()) continue; // 별점이 없는 식당은 건너뛴다 auto [lo, hi] = std::minmax_element(col.begin(), col.end()); std::pair<int, int> key(*lo, *hi); // pair는 앞의 값부터 차례로 견준다 if (best == 0 || key > bestKey) { best = j + 1; bestKey = key; } } if (best == 0) { std::cout << 0 << '\n'; return 0; } int fans = 0; for (const auto& row : grid) { if (!row[best - 1]) continue; int top = *row[best - 1]; for (const auto& cell : row) { if (cell) top = std::max(top, *cell); } if (*row[best - 1] == top) fans++; } std::cout << best << ' ' << bestKey.first << ' ' << bestKey.second << '\n' << fans << '\n';}
Cmain.c · 54 lines
#include <limits.h>#include <stdio.h>#include <stdlib.h>#define MAXN 200#define NONE INT_MIN /* 별점이 없는 칸 */static int grid[MAXN][MAXN];int main(void) { int n, m; char tok[16]; scanf("%d %d", &n, &m); for (int r = 0; r < n; r++) { for (int j = 0; j < m; j++) { scanf("%15s", tok); grid[r][j] = tok[0] == 'x' ? NONE : atoi(tok); } } int best = 0, bestLo = 0, bestHi = 0; /* best가 0이면 아직 고른 식당이 없다 */ for (int j = 0; j < m; j++) { /* 0이 아니라 가장 큰 값·가장 작은 값에서 시작해야 음수 별점도 맞게 나온다 */ int lo = INT_MAX, hi = INT_MIN, count = 0; for (int r = 0; r < n; r++) { if (grid[r][j] == NONE) continue; if (grid[r][j] < lo) lo = grid[r][j]; if (grid[r][j] > hi) hi = grid[r][j]; count++; } if (count == 0) continue; /* 별점이 없는 식당은 건너뛴다 */ if (best == 0 || lo > bestLo || (lo == bestLo && hi > bestHi)) { best = j + 1; bestLo = lo; bestHi = hi; } } if (best == 0) { puts("0"); return 0; } int fans = 0; for (int r = 0; r < n; r++) { if (grid[r][best - 1] == NONE) continue; int top = INT_MIN; for (int j = 0; j < m; j++) { if (grid[r][j] != NONE && grid[r][j] > top) top = grid[r][j]; } if (grid[r][best - 1] == top) fans++; } printf("%d %d %d\n%d\n", best, bestLo, bestHi, fans); return 0;}
Craykonmain.cray · 95 lines
head = Console.ReadNumbers();n = head[0];m = head[1];// 별점이 없는 칸은 빈값으로 둔다grid = [];for (r = 0; r < n; r++){ row = []; foreach (tok in Console.ReadLine().Trim().Split(" ")) { if (tok == "x") { row.Add(null); } else { row.Add(tok.ToNumber()); } } grid.Add(row);}// best가 0이면 아직 고른 식당이 없다best = 0;bestLo = 0;bestHi = 0;for (j = 0; j < m; j++){ // 0이 아니라 처음 만난 별점에서 시작해야 음수 별점도 맞게 나온다 count = 0; lo = 0; hi = 0; for (r = 0; r < n; r++) { v = grid[r][j]; if (v == null) { continue; } if (count == 0) { lo = v; hi = v; } else { lo = Mathf.Min(lo, v); hi = Mathf.Max(hi, v); } count++; } // 별점이 없는 식당은 건너뛴다 if (count == 0) { continue; } if (best == 0 || lo > bestLo || lo == bestLo && hi > bestHi) { best = j + 1; bestLo = lo; bestHi = hi; }}if (best == 0){ Console.WriteLine(0);}else{ fans = 0; foreach (row in grid) { mine = row[best - 1]; if (mine == null) { continue; } // 이 친구가 준 가장 높은 별점: mine에서 시작하면 된다 top = mine; foreach (v in row) { if (v != null) { top = Mathf.Max(top, v); } } if (mine == top) { fans++; } } Console.WriteLine(best + " " + bestLo + " " + bestHi); Console.WriteLine(fans);}