손님 n명이 둥근 탁자에 앉는다.
자리는 0번부터 n − 1번까지 시계 방향으로 번호가 붙어 있고, n − 1번 자리와 0번 자리도 서로 이웃이다.
처음 적힌 손님은 늘 0번 자리에 앉고, 나머지 손님은 1번부터 n − 1번 자리에 한 명씩 앉는다.
두 자리 사이의 거리는 탁자를 따라 짧은 쪽으로 센 자리 차이다(자리 p, q라면 |p − q|와 n − |p − q| 가운데 작은 값).
규칙은 네 가지다.
next A B: A와 B의 거리가 1이다.
apart A B: A와 B의 거리가 1이 아니다.
cw A B: B가 A의 바로 다음 자리(시계 방향)에 앉는다. 즉 B의 자리 = (A의 자리 + 1)을 n으로 나눈 나머지.
far A B k: A와 B의 거리가 k 이상이다.
규칙 m개를 모두 지키는 앉는 방법의 수를 출력하라.
하나 이상이면, 그 가운데 0번 자리부터 차례로 이름을 적었을 때 사전 순으로 가장 앞서는 배치를 이름 사이에 빈칸 하나씩 띄워 한 줄 더 출력한다.
사전 순은 이름을 자리 순서대로 하나씩 비교하고, 이름끼리는 문자열 비교(알파벳 순, 앞부분이 같으면 짧은 쪽이 먼저)로 정한다.
입력
첫 줄에 n과 m, 둘째 줄에 서로 다른 이름 n개, 다음 m줄에 규칙 하나씩. 1 ≤ n ≤ 9, 0 ≤ m ≤ 20, 이름은 1~10글자 영어 소문자, 규칙의 A와 B는 서로 다른 손님, 1 ≤ k ≤ 9
출력
앉는 방법의 수. 1 이상이면 다음 줄에 사전 순으로 가장 앞선 배치
예시 1 · stdin
5 3
mina dan eve bo cal
next mina bo
cw dan eve
far mina cal 2
stdout
2
mina bo cal dan eve
예시 2 · stdin
2 1
bo al
apart al bo
stdout
0
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
손님이 9명이라도 나머지 8명을 앉히는 방법은 8! = 40,320가지라 모두 해 볼 수 있어요. 자리를 1번부터 차례로 채우면서, 방금 앉힌 손님이 나오는 규칙 가운데 두 사람이 다 앉은 것만 바로 검사하고, 어긋나면 그 뒤는 보지 않아요(가지치기). 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞서요. 규칙은 읽을 때 검사 함수로 바꿔 목록에 담아 두면 앉힐 때는 종류를 다시 묻지 않고 부르기만 해요: Python lambda, JavaScript·TypeScript 화살표 함수 (sa, sb) => …(TypeScript는 type Check = (sa: number, sb: number) => boolean), Java BiPredicate<Integer, Integer>와 check.test(…), C# Func<int, int, bool>, C++ std::function<bool(int, int)>과 람다 [k](int sa, int sb) {…}, C는 함수 포인터 int (*check)(int, int, int)와 k를 함께 담은 구조체예요. 크레이콘은 람다가 없어서 모양 (sa, sb, k)를 맞춘 함수 네 개를 만들고, 사전 checks["far"] = 멀리;로 이름에서 함수를 찾아 [함수, a, b, k] 목록에 담은 뒤 r[0](sa, sb, r[3])로 불러요. 함정 ① 늦게 묶이는 k: Python에서 반복문 안의 lambda sa, sb: dist(sa, sb) >= k는 k의 값이 아니라 변수를 기억해서, 나중에 부를 때 마지막 규칙의 k를 봐요 — def at_least(k): return lambda …처럼 함수로 한 번 감싸요. JavaScript의 var k도 반복마다 새로 생기지 않아 똑같이 깨지고, let/const는 반복마다 새로 생겨서 괜찮아요. Java는 effectively final 변수만 람다가 가둘 수 있어 이 실수가 컴파일되지 않고, C#은 반복 몸통 안에서 만든 변수가 반복마다 따로예요. C++는 [k]로 값을 복사해 가둬요. ② n − 1번과 0번이 이웃인 것을 잊고 거리를 |p − q|로만 재기. ③ cw의 방향을 거꾸로 하기. ④ 0번 자리를 고정하지 않아 돌려 앉힌 배치를 따로 세기.
Pythonmain.py · 63 줄
import sysdef main(): lines = sys.stdin.read().split("\n") n, m = map(int, lines[0].split()) names = lines[1].split() index = {name: i for i, name in enumerate(names)} def dist(sa, sb): """둥근 탁자에서 두 자리 사이의 짧은 쪽 거리""" d = abs(sa - sb) return min(d, n - d) def at_least(k): # k를 매개변수로 받아 가둔다. 반복문 안에서 lambda가 k를 바로 쓰면 마지막 k만 보게 된다 return lambda sa, sb: dist(sa, sb) >= k makers = { "next": lambda k: (lambda sa, sb: dist(sa, sb) == 1), "apart": lambda k: (lambda sa, sb: dist(sa, sb) != 1), "cw": lambda k: (lambda sa, sb: (sa + 1) % n == sb), "far": at_least, } rules_of = [[] for _ in range(n)] # 손님마다 그 손님이 나오는 규칙: (검사 함수, a, b) for line in lines[2:2 + m]: kind, x, y, *rest = line.split() a, b = index[x], index[y] check = makers[kind](int(rest[0]) if rest else 0) rules_of[a].append((check, a, b)) rules_of[b].append((check, a, b)) order = sorted(range(1, n), key=lambda g: names[g]) # 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 seat_of = [-1] * n seat_of[0] = 0 # 처음 적힌 손님은 늘 0번 자리 at_seat = [0] * n count = 0 first = None def place(seat): nonlocal count, first if seat == n: count += 1 if first is None: first = " ".join(names[g] for g in at_seat) return for g in order: if seat_of[g] != -1: continue seat_of[g] = seat at_seat[seat] = g # 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) if all(seat_of[a] < 0 or seat_of[b] < 0 or check(seat_of[a], seat_of[b]) for check, a, b in rules_of[g]): place(seat + 1) seat_of[g] = -1 place(1) print(count) if count > 0: print(first)main()
JavaScriptmain.js · 50 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const names = lines[1].trim().split(/\s+/);const index = new Map(names.map((name, i) => [name, i]));// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리const dist = (sa, sb) => Math.min(Math.abs(sa - sb), n - Math.abs(sa - sb));// 규칙 종류마다 "검사 함수를 만드는 함수". far는 k를 가둔 화살표 함수를 돌려준다const makers = { next: () => (sa, sb) => dist(sa, sb) === 1, apart: () => (sa, sb) => dist(sa, sb) !== 1, cw: () => (sa, sb) => (sa + 1) % n === sb, far: (k) => (sa, sb) => dist(sa, sb) >= k,};const rulesOf = Array.from({ length: n }, () => []); // 손님마다 그 손님이 나오는 규칙: { check, a, b }for (let i = 0; i < m; i++) { const [kind, x, y, k] = lines[2 + i].trim().split(/\s+/); const rule = { check: makers[kind](Number(k)), a: index.get(x), b: index.get(y) }; rulesOf[rule.a].push(rule); rulesOf[rule.b].push(rule);}// 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다const order = [...Array(n).keys()].slice(1).sort((g, h) => (names[g] < names[h] ? -1 : 1));const seatOf = new Array(n).fill(-1);seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리const atSeat = new Array(n).fill(0);let count = 0;let first = null;function place(seat) { if (seat === n) { count++; if (first === null) first = atSeat.map((g) => names[g]).join(" "); return; } for (const g of order) { if (seatOf[g] !== -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) const ok = rulesOf[g].every(({ check, a, b }) => seatOf[a] < 0 || seatOf[b] < 0 || check(seatOf[a], seatOf[b])); if (ok) place(seat + 1); seatOf[g] = -1; }}place(1);console.log(count > 0 ? `${count}\n${first}` : "0");
TypeScriptmain.ts · 58 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const names: string[] = lines[1].trim().split(/\s+/);const index = new Map<string, number>(names.map((name, i) => [name, i]));type Check = (sa: number, sb: number) => boolean;interface Rule { check: Check; a: number; b: number;}// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리const dist = (sa: number, sb: number): number => Math.min(Math.abs(sa - sb), n - Math.abs(sa - sb));// 규칙 종류마다 "검사 함수를 만드는 함수". far는 k를 가둔 화살표 함수를 돌려준다const makers: Record<string, (k: number) => Check> = { next: () => (sa, sb) => dist(sa, sb) === 1, apart: () => (sa, sb) => dist(sa, sb) !== 1, cw: () => (sa, sb) => (sa + 1) % n === sb, far: (k) => (sa, sb) => dist(sa, sb) >= k,};const rulesOf: Rule[][] = Array.from({ length: n }, () => []); // 손님마다 그 손님이 나오는 규칙for (let i = 0; i < m; i++) { const [kind, x, y, k] = lines[2 + i].trim().split(/\s+/); const rule: Rule = { check: makers[kind](Number(k)), a: index.get(x)!, b: index.get(y)! }; rulesOf[rule.a].push(rule); rulesOf[rule.b].push(rule);}// 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다const order: number[] = [...Array(n).keys()].slice(1).sort((g, h) => (names[g] < names[h] ? -1 : 1));const seatOf: number[] = new Array<number>(n).fill(-1);seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리const atSeat: number[] = new Array<number>(n).fill(0);let count = 0;let first: string | null = null;function place(seat: number): void { if (seat === n) { count++; if (first === null) first = atSeat.map((g) => names[g]).join(" "); return; } for (const g of order) { if (seatOf[g] !== -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) const ok = rulesOf[g].every(({ check, a, b }) => seatOf[a] < 0 || seatOf[b] < 0 || check(seatOf[a], seatOf[b])); if (ok) place(seat + 1); seatOf[g] = -1; }}place(1);console.log(count > 0 ? `${count}\n${first}` : "0");
JavaMain.java · 85 줄
import java.io.*;import java.util.*;import java.util.function.BiPredicate;public class Main { record Rule(BiPredicate<Integer, Integer> check, int a, int b) {} static int n; static String[] names; static List<List<Rule>> rulesOf = new ArrayList<>(); static Integer[] order; static int[] seatOf, atSeat; static long count = 0; static String first = null; // 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리 static int dist(int sa, int sb) { int d = Math.abs(sa - sb); return Math.min(d, n - d); } static void place(int seat) { if (seat == n) { count++; if (first == null) { StringJoiner sj = new StringJoiner(" "); for (int g : atSeat) sj.add(names[g]); first = sj.toString(); } return; } for (int g : order) { if (seatOf[g] != -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) boolean ok = true; for (Rule r : rulesOf.get(g)) { if (seatOf[r.a()] >= 0 && seatOf[r.b()] >= 0 && !r.check().test(seatOf[r.a()], seatOf[r.b()])) { ok = false; break; } } if (ok) place(seat + 1); seatOf[g] = -1; } } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); n = Integer.parseInt(st.nextToken()); int m = Integer.parseInt(st.nextToken()); names = in.readLine().trim().split("\\s+"); Map<String, Integer> index = new HashMap<>(); for (int i = 0; i < n; i++) { index.put(names[i], i); rulesOf.add(new ArrayList<>()); } for (int i = 0; i < m; i++) { String[] p = in.readLine().trim().split("\\s+"); // 람다는 effectively final 변수만 가둘 수 있다: k는 반복마다 새로 만든다 final int k = p.length > 3 ? Integer.parseInt(p[3]) : 0; BiPredicate<Integer, Integer> check = switch (p[0]) { case "next" -> (sa, sb) -> dist(sa, sb) == 1; case "apart" -> (sa, sb) -> dist(sa, sb) != 1; case "cw" -> (sa, sb) -> (sa + 1) % n == sb; default -> (sa, sb) -> dist(sa, sb) >= k; }; Rule r = new Rule(check, index.get(p[1]), index.get(p[2])); rulesOf.get(r.a()).add(r); rulesOf.get(r.b()).add(r); } // 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 order = new Integer[n - 1]; for (int i = 1; i < n; i++) order[i - 1] = i; Arrays.sort(order, (g, h) -> names[g].compareTo(names[h])); seatOf = new int[n]; Arrays.fill(seatOf, -1); seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리 atSeat = new int[n]; place(1); System.out.println(count > 0 ? count + "\n" + first : "0"); }}
C#Main.cs · 79 줄
using System;using System.Collections.Generic;using System.Linq;class Program{ record Rule(Func<int, int, bool> Check, int A, int B); static int n; static string[] names; static List<Rule>[] rulesOf; static int[] order, seatOf, atSeat; static long count = 0; static string first = null; // 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리 static int Dist(int sa, int sb) { int d = Math.Abs(sa - sb); return Math.Min(d, n - d); } static void Place(int seat) { if (seat == n) { count++; if (first == null) first = string.Join(" ", atSeat.Select(g => names[g])); return; } foreach (int g in order) { if (seatOf[g] != -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) bool ok = rulesOf[g].All(r => seatOf[r.A] < 0 || seatOf[r.B] < 0 || r.Check(seatOf[r.A], seatOf[r.B])); if (ok) Place(seat + 1); seatOf[g] = -1; } } static void Main() { int[] nm = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); n = nm[0]; int m = nm[1]; names = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); var index = new Dictionary<string, int>(); rulesOf = new List<Rule>[n]; for (int i = 0; i < n; i++) { index[names[i]] = i; rulesOf[i] = new List<Rule>(); } for (int i = 0; i < m; i++) { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int k = p.Length > 3 ? int.Parse(p[3]) : 0; // 반복 몸통 안에서 만든 변수라 람다마다 따로 갇힌다 Func<int, int, bool> check = p[0] switch { "next" => (sa, sb) => Dist(sa, sb) == 1, "apart" => (sa, sb) => Dist(sa, sb) != 1, "cw" => (sa, sb) => (sa + 1) % n == sb, _ => (sa, sb) => Dist(sa, sb) >= k, }; var r = new Rule(check, index[p[1]], index[p[2]]); rulesOf[r.A].Add(r); rulesOf[r.B].Add(r); } // 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 order = Enumerable.Range(1, n - 1).OrderBy(g => names[g], StringComparer.Ordinal).ToArray(); seatOf = Enumerable.Repeat(-1, n).ToArray(); seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리 atSeat = new int[n]; Place(1); Console.WriteLine(count > 0 ? count + "\n" + first : "0"); }}
C++main.cpp · 82 줄
#include <algorithm>#include <cstdlib>#include <functional>#include <iostream>#include <map>#include <string>#include <vector>struct Rule { std::function<bool(int, int)> check; int a, b;};int n;std::vector<std::string> names;std::vector<std::vector<Rule>> rulesOf; // 손님마다 그 손님이 나오는 규칙std::vector<int> order, seatOf, atSeat;long long countAll = 0;std::string first;// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리int dist(int sa, int sb) { int d = std::abs(sa - sb); return std::min(d, n - d);}void place(int seat) { if (seat == n) { if (countAll++ == 0) { for (int i = 0; i < n; i++) first += (i ? " " : "") + names[atSeat[i]]; } return; } for (int g : order) { if (seatOf[g] != -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) bool ok = std::all_of(rulesOf[g].begin(), rulesOf[g].end(), [](const Rule& r) { return seatOf[r.a] < 0 || seatOf[r.b] < 0 || r.check(seatOf[r.a], seatOf[r.b]); }); if (ok) place(seat + 1); seatOf[g] = -1; }}int main() { int m; std::cin >> n >> m; names.resize(n); std::map<std::string, int> index; for (int i = 0; i < n; i++) { std::cin >> names[i]; index[names[i]] = i; } rulesOf.assign(n, {}); for (int i = 0; i < m; i++) { std::string kind, x, y; std::cin >> kind >> x >> y; std::function<bool(int, int)> check; if (kind == "next") check = [](int sa, int sb) { return dist(sa, sb) == 1; }; else if (kind == "apart") check = [](int sa, int sb) { return dist(sa, sb) != 1; }; else if (kind == "cw") check = [](int sa, int sb) { return (sa + 1) % n == sb; }; else { int k; std::cin >> k; check = [k](int sa, int sb) { return dist(sa, sb) >= k; }; // [k]: 지금 값을 복사해 가둔다 } Rule r{check, index[x], index[y]}; rulesOf[r.a].push_back(r); rulesOf[r.b].push_back(r); } // 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 for (int i = 1; i < n; i++) order.push_back(i); std::sort(order.begin(), order.end(), [](int g, int h) { return names[g] < names[h]; }); seatOf.assign(n, -1); seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리 atSeat.assign(n, 0); place(1); std::cout << countAll << '\n'; if (countAll > 0) std::cout << first << '\n';}
Cmain.c · 99 줄
#include <stdio.h>#include <stdlib.h>#include <string.h>static int n;/* 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리 */int dist(int sa, int sb) { int d = abs(sa - sb); return d < n - d ? d : n - d;}/* 규칙 검사 함수들: 모양(int, int, int)을 맞춰 두면 함수 포인터 하나로 부를 수 있다 */int rule_next(int sa, int sb, int k) { (void)k; return dist(sa, sb) == 1; }int rule_apart(int sa, int sb, int k) { (void)k; return dist(sa, sb) != 1; }int rule_cw(int sa, int sb, int k) { (void)k; return (sa + 1) % n == sb; }int rule_far(int sa, int sb, int k) { return dist(sa, sb) >= k; }typedef struct { int (*check)(int, int, int); /* 함수 포인터 */ int a, b, k;} Rule;static char names[9][16];static Rule rules[20];static int rules_of[9][20], nrules_of[9]; /* 손님마다 그 손님이 나오는 규칙 번호 */static int order[9], seat_of[9], at_seat[9];static long count = 0;static char first[200];int find(const char *s) { for (int i = 0; i < n; i++) if (strcmp(names[i], s) == 0) return i; return -1;}void place(int seat) { if (seat == n) { if (count++ == 0) { first[0] = '\0'; for (int i = 0; i < n; i++) { if (i) strcat(first, " "); strcat(first, names[at_seat[i]]); } } return; } for (int oi = 0; oi < n - 1; oi++) { int g = order[oi]; if (seat_of[g] != -1) continue; seat_of[g] = seat; at_seat[seat] = g; /* 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) */ int ok = 1; for (int j = 0; j < nrules_of[g] && ok; j++) { Rule *r = &rules[rules_of[g][j]]; if (seat_of[r->a] >= 0 && seat_of[r->b] >= 0 && !r->check(seat_of[r->a], seat_of[r->b], r->k)) ok = 0; } if (ok) place(seat + 1); seat_of[g] = -1; }}int by_name(const void *x, const void *y) { return strcmp(names[*(const int *)x], names[*(const int *)y]);}int main(void) { int m; scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) scanf("%15s", names[i]); for (int i = 0; i < m; i++) { char kind[8], x[16], y[16]; scanf("%7s %15s %15s", kind, x, y); Rule *r = &rules[i]; r->a = find(x); r->b = find(y); r->k = 0; if (strcmp(kind, "next") == 0) r->check = rule_next; else if (strcmp(kind, "apart") == 0) r->check = rule_apart; else if (strcmp(kind, "cw") == 0) r->check = rule_cw; else { r->check = rule_far; scanf("%d", &r->k); } rules_of[r->a][nrules_of[r->a]++] = i; rules_of[r->b][nrules_of[r->b]++] = i; } /* 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 */ for (int i = 1; i < n; i++) order[i - 1] = i; qsort(order, n - 1, sizeof(int), by_name); for (int i = 0; i < n; i++) seat_of[i] = -1; seat_of[0] = 0; /* 처음 적힌 손님은 늘 0번 자리 */ at_seat[0] = 0; place(1); printf("%ld\n", count); if (count > 0) printf("%s\n", first); return 0;}
Craykonmain.cray · 127 줄
// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리거리(sa, sb){ d = 수학.절댓값(sa - sb); 돌려주기 수학.작은수(d, n - d);}// 규칙 검사 함수들. 크레이콘에는 람다가 없으니 모양(sa, sb, k)을 맞춘 함수를 이름으로 넘긴다이웃(sa, sb, k){ 돌려주기 거리(sa, sb) == 1;}떨어짐(sa, sb, k){ 돌려주기 거리(sa, sb) != 1;}시계방향(sa, sb, k){ 돌려주기 (sa + 1) % n == sb;}멀리(sa, sb, k){ 돌려주기 거리(sa, sb) >= k;}// 이름 순 비교(정렬 기준 함수)이름순(g, h){ 만약 (names[g] < names[h]) { 돌려주기 -1; } 돌려주기 1;}앉히기(seat){ 만약 (seat == n) { count += 1; 만약 (count == 1) { first = names[atSeat[0]]; 반복 (s = 1; s < n; s++) { first += " " + names[atSeat[s]]; } } 돌려주기; } 각각 (g 에서 order) { 만약 (seatOf[g] == -1) { seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) ok = 참; 각각 (r 에서 rulesOf[g]) { sa = seatOf[r[1]]; sb = seatOf[r[2]]; 만약 (sa >= 0 && sb >= 0 && !r[0](sa, sb, r[3])) { ok = 거짓; 그만; } } 만약 (ok) { 앉히기(seat + 1); } seatOf[g] = -1; } }}nm = 콘솔.수들읽기();n = nm[0];m = nm[1];names = 콘솔.줄읽기().공백제거().나누기(" ");index = 사전();rulesOf = [];반복 (i = 0; i < n; i++){ index[names[i]] = i; rulesOf.넣기([]);}checks = 사전(); // 규칙 이름 → 검사 함수checks["next"] = 이웃;checks["apart"] = 떨어짐;checks["cw"] = 시계방향;checks["far"] = 멀리;반복 (i = 0; i < m; i++){ p = 콘솔.줄읽기().공백제거().나누기(" "); kval = 0; 만약 (p.개수 > 3) { kval = p[3].수로변환(); } rule = [checks[p[0]], index[p[1]], index[p[2]], kval]; // [검사 함수, a, b, k] rulesOf[rule[1]].넣기(rule); rulesOf[rule[2]].넣기(rule);}// 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다order = [];반복 (i = 1; i < n; i++){ order.넣기(i);}order.정렬(이름순);seatOf = 새목록(n, -1);seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리atSeat = 새목록(n, 0);count = 0;first = "";앉히기(1);콘솔.쓰기(count);만약 (count > 0){ 콘솔.쓰기(first);}