import React, { useState } from 'react'; import { ChevronRight, ChevronLeft, CheckCircle2, Info, Network, Grid3X3, ArrowRight } from 'lucide-react'; // --- 資料定義 --- const nodes = [ // Base Nouns { id: 'bay', label: 'បាយ (bay)', eng: '飯', x: 100, y: 150, type: 'core' }, { id: 'kuy', label: 'គុយទាវ (kuyteav)', eng: '粿條/麵', x: 100, y: 400, type: 'core' }, { id: 'salat', label: 'សាឡាត់ (salat)', eng: '沙拉', x: 100, y: 280, type: 'core' }, // Modifiers 1 (Cooking / Type) { id: 'cha', label: 'ឆា (cha)', eng: '炒', x: 250, y: 150, type: 'mod1' }, { id: 'sut', label: 'ស៊ុត (sut)', eng: '蛋', x: 250, y: 400, type: 'mod1' }, // The crucial "Meat" classifier node { id: 'sach', label: 'សាច់ (sach)', eng: '肉 (分類詞)', x: 400, y: 280, type: 'class' }, // Proteins (Animals / Tofu) { id: 'chruk', label: 'ជ្រូក (chruk)', eng: '豬', x: 550, y: 180, type: 'protein' }, { id: 'ko', label: 'គោ (ko)', eng: '牛', x: 550, y: 380, type: 'protein' }, { id: 'trey', label: 'ត្រី (trey)', eng: '魚', x: 550, y: 280, type: 'protein' }, ]; const edges = [ // Bay chain { source: 'bay', target: 'cha', label: '+ ឆា', id: 'e1' }, { source: 'cha', target: 'sach', label: '+ សាច់', id: 'e2' }, // Kuyteav chain { source: 'kuy', target: 'sut', label: '+ ស៊ុត', id: 'e3' }, { source: 'sut', target: 'sach', label: '+ សាច់', id: 'e4' }, // Salat chain { source: 'salat', target: 'sach', label: '+ សាច់', id: 'e5' }, // Sach (Meat) chain { source: 'sach', target: 'chruk', label: '豬肉', id: 'e6' }, { source: 'sach', target: 'ko', label: '牛肉', id: 'e7' }, // Exception (Fish) { source: 'salat', target: 'trey', label: '直接連接', id: 'e8' }, ]; export default function KhmerSemanticsApp() { const [activeMode, setActiveMode] = useState('graph'); const [graphStep, setGraphStep] = useState(0); const [matrixStep, setMatrixStep] = useState(0); // --- 圖表法元件 --- const GraphView = () => { const steps = [ { title: "步驟 1:確立主食核心節點", desc: "掃描語料字首,我們發現大量的「បាយ」(出現5次,對應rice飯)、「គុយទាវ」(出現4次,對應noodles麵) 以及「សាឡាត់」(出現2次,對應salad沙拉)。它們是句子的起點。" }, { title: "步驟 2:建構修飾語鏈條", desc: "高棉語是「由左至右」修飾。以飯為例:បាយ (飯) 接上 ឆា (炒),變成「炒飯」。គុយទាវ (麵) 接上 ស៊ុត (蛋),變成「雞蛋麵」。" }, { title: "步驟 3:發現神祕的樞紐節點「សាច់ (sach)」", desc: "這題最精彩的地方來了!你會發現「炒飯」和「沙拉」要接續「牛、豬、水牛」之前,全部都要先經過一個高頻字「សាច់」(出現6次)。這個字正是「肉 (Meat)」!" }, { title: "步驟 4:語義分類的例外 (Exception)", desc: "觀察 fish salad (សាឡាត់ត្រី):沙拉(salat) 竟然直接連到魚(trey),中間沒有經過「肉(sach)」。這證明了在高棉語的語義分類中,「魚」不屬於「肉類」!" } ]; return (

{steps[graphStep].title}

{steps[graphStep].desc}

{/* Edges */} {graphStep >= 1 && edges.map((edge) => { // Edge visibility logic if (graphStep === 1 && (edge.id !== 'e1' && edge.id !== 'e3' && edge.id !== 'e5' && edge.id !== 'e8')) return null; if (graphStep === 2 && edge.id === 'e8') return null; // Hide fish temporarily in step 2 if (graphStep < 3 && edge.id === 'e8') return null; const sourceNode = nodes.find(n => n.id === edge.source); const targetNode = nodes.find(n => n.id === edge.target); const isException = edge.id === 'e8'; return ( {graphStep >= 2 && !isException && ( )} {graphStep >= 2 && !isException && ( {edge.label} )} ); })} {/* Nodes */} {nodes.map((node) => { if (graphStep === 0 && node.type !== 'core') return null; if (graphStep === 1 && node.type === 'class') return null; if (graphStep < 3 && node.id === 'trey') return null; return ( = 2 ? '#fbbf24' : 'white'} strokeWidth={node.type === 'class' && graphStep >= 2 ? '6' : '3'} className="drop-shadow-sm" /> {node.label.split(' ')[0]} {node.eng.split(' ')[0]} {graphStep >= 2 && node.type === 'class' && ( )} ); })}
{[0, 1, 2, 3].map(step => (
))}
); }; // --- 矩陣法元件 --- const MatrixView = () => { const steps = [ { title: "步驟 1:建立詞頻與位置矩陣", desc: "首先,計算高頻詞。បាយ(飯)出現5次,សាច់(肉)出現6次。特別注意它們的位置:បាយ 總是在句首 (Head),而 សាច់ 總是在句中 (Middle)。" }, { title: "步驟 2:核心語序代數推導", desc: "提取:សាឡាត់ត្រី = fish salad (沙拉+魚);សាឡាត់សាច់គោ = beef salad (沙拉+肉+牛)。\n由此得出高棉語的公式:【名詞 + 修飾語】。" }, { title: "步驟 3:發現「泛稱分類詞」的規律", desc: "矩陣揭露了一個重大差異:pork, beef, buffalo 都帶有 សាច់ (sach / 肉)。\n公式:sach(肉) + ko(牛) = beef。\n公式:sach(肉) + chruk(豬) = pork。" }, { title: "步驟 4:利用空缺 (Gaps) 找出例外", desc: "在矩陣中,Fish(ត្រី) 和 Tofu(តៅហ៊ូ) 的「含 សាច់ (sach)」欄位是空白的(False)。\n結論:高棉語的 meat(សាច់) 只用於陸地哺乳類,海鮮與素食不加此分類詞!" } ]; const matrixData = [ { word: 'បាយ (bay)', type: '主食', freq: 5, pos: '首 (Head)', hasSach: '-', meaning: matrixStep >= 1 ? 'Rice (飯)' : '?' }, { word: 'សាច់ (sach)', type: '樞紐', freq: 6, pos: '中 (Mid)', hasSach: '-', meaning: matrixStep >= 2 ? 'Meat (肉)' : '?' }, { word: 'គោ (ko)', type: '食材', freq: 2, pos: '尾 (Tail)', hasSach: true, meaning: matrixStep >= 2 ? 'Cow (牛)' : '?' }, { word: 'ជ្រូក (chruk)', type: '食材', freq: 2, pos: '尾 (Tail)', hasSach: true, meaning: matrixStep >= 2 ? 'Pig (豬)' : '?' }, { word: 'ត្រី (trey)', type: '食材', freq: 2, pos: '尾 (Tail)', hasSach: false, meaning: matrixStep >= 1 ? 'Fish (魚)' : '?' }, { word: 'តៅហ៊ូ (tofu)', type: '食材', freq: 1, pos: '尾 (Tail)', hasSach: false, meaning: matrixStep >= 3 ? 'Tofu (豆腐)' : '?' }, ]; return (

{steps[matrixStep].title}

{steps[matrixStep].desc}

{/* 矩陣表格 */}
{matrixData.map((row, idx) => ( = 5) ? 'bg-yellow-50' : (matrixStep === 2 && row.hasSach === true) ? 'bg-orange-50' : (matrixStep === 3 && row.hasSach === false) ? 'bg-red-50' : '' }`}> ))}
高棉語單詞 詞類 頻率 位置 前置「សាច់」(肉) 破譯語義
{row.word} {row.type} {row.freq} {row.pos} {row.hasSach === true ? : row.hasSach === false ? X (無) : row.hasSach} {row.meaning}
{/* 公式推導區塊 */} {matrixStep >= 1 && (

語法與分類詞代數 (Syntax & Classifier Logic)

{matrixStep >= 1 && (
Word Order Check: សាឡាត់(salat) + ត្រី(trey) = fish salad ➔ Noun (Head) + Modifier (Tail)
)} {matrixStep >= 2 && (
សាច់ (sach):
sach + ko(牛) = beef sach + chruk(豬) = pork
)} {matrixStep >= 3 && (
// 語義分類例外偵測 (Semantic Exception Detection)
If fish = ត្រី (trey), why not សាច់ត្រី (sach trey)?
解答:高棉語將「魚/豆腐」排除在「肉類(sach)」分類之外
)}
)}
{[0, 1, 2, 3].map(step => (
))}
); }; return (
{/* Header */}

語義分類解題思維動態模擬

2024 UKLO Round 1 問題3:高棉語 (Khmer) 菜單破譯

{/* Info Alert */}
解題核心:從「句法結構」看見「語義分類」
這題並非單純的單字替換!透過分析,我們發現英文的 Beef (牛肉) 和 Pork (豬肉) 在高棉語中必須拆解為 「肉 + 牛」「肉 + 豬」。但最有趣的是,Fish (魚) 前面並不會加上「肉」字。這種語言中隱藏的「語義分類詞 (Classifier)」,正是這道題目的靈魂!
{/* Main Content Area */}
{activeMode === 'graph' ? : }