import sysfrom functools import cmp_to_keylines = sys.stdin.read().split("\n")n, c, k = map(int, lines[0].split())types = lines[1].split()# 기준마다 (열 번호, 내림차순인가)keys = [(int(t[1:]) - 1, t[0] == "-") for t in lines[2].split()]rows = []for i in range(n): cells = lines[3 + i].split() # 값이 없는 칸은 None, 수 열은 int, 문자열 열은 그대로 rows.append([None if v == "?" else (int(v) if types[j] == "N" else v) for j, v in enumerate(cells)])def compare(x, y): for col, desc in keys: a, b = rows[x][col], rows[y][col] if a is None or b is None: if a is None and b is None: continue return 1 if a is None else -1 # 값이 없는 칸은 방향과 상관없이 뒤로 if a != b: r = -1 if a < b else 1 # 문자열의 < 는 글자 코드 순서다 return -r if desc else r return 0# sorted는 안정 정렬이라 모든 기준이 같으면 입력 순서가 남는다order = sorted(range(n), key=cmp_to_key(compare))print(" ".join(str(i + 1) for i in order))
JavaScriptmain.js · 32 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, c, k] = lines[0].split(" ").map(Number);const types = lines[1].trim().split(" ");// 기준마다 열 번호와 방향const keys = lines[2].trim().split(" ").map((t) => ({ col: Number(t.slice(1)) - 1, desc: t[0] === "-" }));const rows = [];for (let i = 0; i < n; i++) { const cells = lines[3 + i].trim().split(" "); // 값이 없는 칸은 null, 수 열은 수로, 문자열 열은 그대로 rows.push(cells.map((v, j) => (v === "?" ? null : types[j] === "N" ? Number(v) : v)));}function compare(x, y) { for (const { col, desc } of keys) { const a = rows[x][col]; const b = rows[y][col]; if (a === null || b === null) { if (a === null && b === null) continue; return a === null ? 1 : -1; // 값이 없는 칸은 방향과 상관없이 뒤로 } if (a !== b) { const r = a < b ? -1 : 1; // 문자열의 < 는 글자 코드 순서다(localeCompare가 아니다) return desc ? -r : r; } } return 0;}// Array.prototype.sort는 안정 정렬이라(ES2019부터) 모든 기준이 같으면 입력 순서가 남는다const order = Array.from({ length: n }, (_, i) => i).sort(compare);console.log(order.map((i) => i + 1).join(" "));
TypeScriptmain.ts · 40 行
import { readFileSync } from "node:fs";type Cell = number | string | null;interface Key { col: number; desc: boolean;}const lines: string[] = readFileSync(0, "utf8").split("\n");const [n] = lines[0].split(" ").map(Number);const types: string[] = lines[1].trim().split(" ");// 기준마다 열 번호와 방향const keys: Key[] = lines[2].trim().split(" ").map((t) => ({ col: Number(t.slice(1)) - 1, desc: t[0] === "-" }));const rows: Cell[][] = [];for (let i = 0; i < n; i++) { const cells: string[] = lines[3 + i].trim().split(" "); // 값이 없는 칸은 null, 수 열은 수로, 문자열 열은 그대로 rows.push(cells.map((v, j): Cell => (v === "?" ? null : types[j] === "N" ? Number(v) : v)));}function compare(x: number, y: number): number { for (const { col, desc } of keys) { const a: Cell = rows[x][col]; const b: Cell = rows[y][col]; if (a === null || b === null) { if (a === null && b === null) continue; return a === null ? 1 : -1; // 값이 없는 칸은 방향과 상관없이 뒤로 } if (a !== b) { const r: number = a < b ? -1 : 1; // 문자열의 < 는 글자 코드 순서다(localeCompare가 아니다) return desc ? -r : r; } } return 0;}// Array.prototype.sort는 안정 정렬이라(ES2019부터) 모든 기준이 같으면 입력 순서가 남는다const order: number[] = Array.from({ length: n }, (_, i) => i).sort(compare);console.log(order.map((i) => i + 1).join(" "));
JavaMain.java · 52 行
import java.io.*;import java.util.*;public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int n = Integer.parseInt(st.nextToken()); int c = Integer.parseInt(st.nextToken()); String[] types = br.readLine().trim().split(" "); String[] keyTokens = br.readLine().trim().split(" "); boolean[][] empty = new boolean[n][c]; int[][] num = new int[n][c]; // 수 열의 값 String[][] text = new String[n][c]; // 문자열 열의 값 for (int i = 0; i < n; i++) { String[] cells = br.readLine().trim().split(" "); for (int j = 0; j < c; j++) { if (cells[j].equals("?")) empty[i][j] = true; else if (types[j].equals("N")) num[i][j] = Integer.parseInt(cells[j]); else text[i][j] = cells[j]; } } // 기준 하나마다 Comparator를 만들고 thenComparing으로 잇는다 Comparator<Integer> chain = null; for (String t : keyTokens) { final int col = Integer.parseInt(t.substring(1)) - 1; final boolean desc = t.charAt(0) == '-'; final boolean numeric = types[col].equals("N"); Comparator<Integer> one = (x, y) -> { boolean ex = empty[x][col], ey = empty[y][col]; if (ex || ey) return Boolean.compare(ex, ey); // 값이 없는 칸은 방향과 상관없이 뒤로 // 뺄셈(a - b)은 넘칠 수 있으니 Integer.compare를 쓴다. compareTo는 글자 코드 순서다 int r = numeric ? Integer.compare(num[x][col], num[y][col]) : text[x][col].compareTo(text[y][col]); return desc ? -r : r; }; chain = chain == null ? one : chain.thenComparing(one); } List<Integer> order = new ArrayList<>(); for (int i = 0; i < n; i++) order.add(i); order.sort(chain); // List.sort는 안정 정렬이라 모든 기준이 같으면 입력 순서가 남는다 StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { if (i > 0) sb.append(' '); sb.append(order.get(i) + 1); } System.out.println(sb); }}
C#Main.cs · 49 行
using System;using System.Linq;class Program{ static void Main() { var head = Console.ReadLine()!.Split(' '); int n = int.Parse(head[0]), c = int.Parse(head[1]); var types = Console.ReadLine()!.Trim().Split(' '); var keyTokens = Console.ReadLine()!.Trim().Split(' '); var keyCol = keyTokens.Select(t => int.Parse(t.Substring(1)) - 1).ToArray(); var keyDesc = keyTokens.Select(t => t[0] == '-').ToArray(); var empty = new bool[n, c]; var num = new int[n, c]; // 수 열의 값 var text = new string[n, c]; // 문자열 열의 값 for (int i = 0; i < n; i++) { var cells = Console.ReadLine()!.Trim().Split(' '); for (int j = 0; j < c; j++) { if (cells[j] == "?") empty[i, j] = true; else if (types[j] == "N") num[i, j] = int.Parse(cells[j]); else text[i, j] = cells[j]; } } var order = Enumerable.Range(0, n).ToArray(); Array.Sort(order, (x, y) => { for (int q = 0; q < keyCol.Length; q++) { int col = keyCol[q]; bool ex = empty[x, col], ey = empty[y, col]; if (ex || ey) { if (ex && ey) continue; return ex ? 1 : -1; // 값이 없는 칸은 방향과 상관없이 뒤로 } // 뺄셈(a - b)은 넘칠 수 있으니 CompareTo를 쓴다. CompareOrdinal은 글자 코드 순서다 int r = types[col] == "N" ? num[x, col].CompareTo(num[y, col]) : string.CompareOrdinal(text[x, col], text[y, col]); if (r != 0) return keyDesc[q] ? -r : r; } return x.CompareTo(y); // Array.Sort는 안정 정렬이 아니라서 입력 순서를 마지막 기준으로 넣는다 }); Console.WriteLine(string.Join(" ", order.Select(i => i + 1))); }}
C++main.cpp · 63 行
#include <algorithm>#include <iostream>#include <numeric>#include <string>#include <vector>using namespace std;struct Cell { bool empty = false; int num = 0; // 수 열의 값 string text; // 문자열 열의 값};int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, c, k; cin >> n >> c >> k; vector<char> types(c); for (auto &t : types) cin >> t; vector<int> keyCol(k); vector<bool> keyDesc(k); for (int q = 0; q < k; q++) { string t; cin >> t; keyDesc[q] = t[0] == '-'; keyCol[q] = stoi(t.substr(1)) - 1; } vector<vector<Cell>> rows(n, vector<Cell>(c)); for (auto &row : rows) { for (int j = 0; j < c; j++) { string v; cin >> v; if (v == "?") row[j].empty = true; else if (types[j] == 'N') row[j].num = stoi(v); else row[j].text = v; } } vector<int> order(n); iota(order.begin(), order.end(), 0); // stable_sort는 모든 기준이 같으면 입력 순서를 지킨다(sort는 지키지 않는다) // 비교 함수는 'x가 y보다 앞인가'를 bool로 답한다 stable_sort(order.begin(), order.end(), [&](int x, int y) { for (int q = 0; q < k; q++) { const Cell &a = rows[x][keyCol[q]]; const Cell &b = rows[y][keyCol[q]]; if (a.empty || b.empty) { if (a.empty && b.empty) continue; return b.empty; // 값이 없는 칸은 방향과 상관없이 뒤로 } if (types[keyCol[q]] == 'N') { if (a.num != b.num) return keyDesc[q] ? a.num > b.num : a.num < b.num; } else { if (a.text != b.text) return keyDesc[q] ? a.text > b.text : a.text < b.text; // 글자 코드 순서 } } return false; }); for (int i = 0; i < n; i++) cout << (i ? " " : "") << order[i] + 1; cout << "\n"; return 0;}
Cmain.c · 61 行
#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXN 10000#define MAXC 6static char types[MAXC];static int keyCol[MAXC], keyDesc[MAXC], k;static char empty[MAXN][MAXC];static int num[MAXN][MAXC]; /* 수 열의 값 */static char text[MAXN][MAXC][9]; /* 문자열 열의 값(8글자까지) */static int order[MAXN];static int compare(const void *pa, const void *pb) { int x = *(const int *)pa, y = *(const int *)pb; for (int q = 0; q < k; q++) { int col = keyCol[q]; if (empty[x][col] || empty[y][col]) { if (empty[x][col] && empty[y][col]) continue; return empty[x][col] ? 1 : -1; /* 값이 없는 칸은 방향과 상관없이 뒤로 */ } int r; if (types[col] == 'N') { /* 뺄셈(a - b)은 넘칠 수 있으니 비교 두 번으로 -1, 0, 1을 만든다 */ r = (num[x][col] > num[y][col]) - (num[x][col] < num[y][col]); } else { r = strcmp(text[x][col], text[y][col]); /* 글자 코드 순서 */ } if (r != 0) return keyDesc[q] ? -r : r; } return (x > y) - (x < y); /* qsort는 안정 정렬이 아니라서 입력 순서를 마지막 기준으로 넣는다 */}int main(void) { int n, c; char tok[16]; if (scanf("%d %d %d", &n, &c, &k) != 3) return 1; for (int j = 0; j < c; j++) { scanf("%15s", tok); types[j] = tok[0]; } for (int q = 0; q < k; q++) { scanf("%15s", tok); keyDesc[q] = tok[0] == '-'; keyCol[q] = atoi(tok + 1) - 1; } for (int i = 0; i < n; i++) { for (int j = 0; j < c; j++) { scanf("%15s", tok); if (strcmp(tok, "?") == 0) empty[i][j] = 1; else if (types[j] == 'N') num[i][j] = atoi(tok); else strcpy(text[i][j], tok); } order[i] = i; } qsort(order, n, sizeof order[0], compare); for (int i = 0; i < n; i++) printf(i ? " %d" : "%d", order[i] + 1); printf("\n"); return 0;}
Craykonmain.cray · 78 行
첫줄 = コンソール.数読み();n = 첫줄[0];c = 첫줄[1];k = 첫줄[2];types = コンソール.行読み().分ける(" ");// 기준마다 열 번호와 방향keyCol = [];keyDesc = [];それぞれ (t の中 コンソール.行読み().分ける(" ")){ keyCol.追加(t.切り出す(1).数に() - 1); keyDesc.追加(t[0] == "-");}rows = [];order = [];繰り返す (i = 0; i < n; i++){ cells = コンソール.行読み().分ける(" "); 繰り返す (j = 0; j < c; j++) { もし (cells[j] == "?") { cells[j] = なし; } でなければ もし (types[j] == "N") { cells[j] = cells[j].数に(); // 수로 바꿔 두지 않으면 "10" < "9"처럼 문자열로 비교된다 } } rows.追加(cells); order.追加(i);}// 앞이 먼저면 음수, 같으면 0, 뒤가 먼저면 양수compareRows(x, y){ 繰り返す (q = 0; q < k; q++) { a = rows[x][keyCol[q]]; b = rows[y][keyCol[q]]; もし (a == なし || b == なし) { もし (a == なし && b == なし) { 次へ; } もし (a == なし) { 返す 1; // 값이 없는 칸은 방향과 상관없이 뒤로 } 返す -1; } もし (a != b) { r = 1; もし (a < b) { r = -1; } もし (keyDesc[q]) { 返す -r; } 返す r; } } 返す 0;}// 정렬(비교함수)는 안정 정렬이라 모든 기준이 같으면 입력 순서가 남는다order.並べ替え(compareRows);out = [];それぞれ (i の中 order){ out.追加(i + 1);}コンソール.書く(out.つなぐ(" "));