+ return (
+
+
+
Data Structures and Algorithms
Interactive explorations of elementary data structures and algorithms.
@@ -68,6 +90,9 @@ const InteractiveGallery = () => {
{filteredInteractives.length === 0 &&
No interactives found matching your search.
}
-
;
+
+
+
+ );
};
export default InteractiveGallery;
\ No newline at end of file
diff --git a/src/components/InteractiveIndex.tsx b/src/components/InteractiveIndex.tsx
index adb4608..cbe4515 100644
--- a/src/components/InteractiveIndex.tsx
+++ b/src/components/InteractiveIndex.tsx
@@ -45,6 +45,15 @@ const allInteractives: Interactive[] = [
path: '/game-of-sim',
theme: 'Games',
dateAdded: '2024-03-10'
+ },
+ {
+ id: 'ternary-search-trick',
+ title: 'Ternary Search Magic Trick',
+ description: 'Experience the magic of ternary search! Think of a number and watch as the cards reveal it through mathematical calculations.',
+ tags: ['ternary', 'magic', 'numbers', 'trick', 'data-structures', 'search'],
+ path: '/ternary-search-trick',
+ theme: 'Data Structures',
+ dateAdded: '2024-07-20'
}
];
diff --git a/src/components/TernarySearchTrick.tsx b/src/components/TernarySearchTrick.tsx
new file mode 100644
index 0000000..91157c2
--- /dev/null
+++ b/src/components/TernarySearchTrick.tsx
@@ -0,0 +1,331 @@
+import React, { useState } from 'react';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+import { Button } from '@/components/ui/button';
+import { Badge } from '@/components/ui/badge';
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
+import { RotateCcw, Wand2, Info } from 'lucide-react';
+import SocialShare from '@/components/SocialShare';
+
+interface TernarySearchTrickProps {
+ showSocialShare?: boolean;
+}
+
+const TernarySearchTrick: React.FC
= ({ showSocialShare = true }) => {
+ const [step, setStep] = useState<'cards' | 'final-question' | 'result'>('cards');
+ const [cardSelections, setCardSelections] = useState<{
+ card1: 'left' | 'right' | 'missing' | null;
+ card2: 'left' | 'right' | 'missing' | null;
+ card3: 'left' | 'right' | 'missing' | null;
+ }>({
+ card1: null,
+ card2: null,
+ card3: null
+ });
+ const [isBiggerThan13, setIsBiggerThan13] = useState(null);
+ const [calculatedNumber, setCalculatedNumber] = useState(null);
+
+ const cardData = {
+ card1: {
+ left: [5, 6, 7, 8, 9, 10, 11, 12, 13, 32, 33, 34, 35, 36, 37, 38, 39, 40],
+ right: [14, 15, 16, 17, 18, 19, 20, 21, 22]
+ },
+ card2: {
+ left: [2, 3, 4, 11, 12, 13, 20, 21, 22, 29, 30, 31, 38, 39, 40],
+ right: [5, 6, 7, 14, 15, 16, 23, 24, 25, 32, 33, 34]
+ },
+ card3: {
+ left: [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40],
+ right: [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38]
+ }
+ };
+
+ const resetTrick = () => {
+ setStep('cards');
+ setCardSelections({
+ card1: null,
+ card2: null,
+ card3: null
+ });
+ setIsBiggerThan13(null);
+ setCalculatedNumber(null);
+ };
+
+ const handleCardSelection = (cardNumber: 1 | 2 | 3, side: 'left' | 'right' | 'missing') => {
+ setCardSelections(prev => ({
+ ...prev,
+ [`card${cardNumber}`]: side
+ }));
+ };
+
+ const handleContinue = () => {
+ if (cardSelections.card1 && cardSelections.card2 && cardSelections.card3) {
+ setStep('final-question');
+ }
+ };
+
+ const handleFinalAnswer = (biggerThan13: boolean) => {
+ setIsBiggerThan13(biggerThan13);
+
+ // Calculate the number
+ let guess = 0;
+
+ // Card 1: left adds 9, right subtracts 9, missing adds 0
+ if (cardSelections.card1 === 'left') guess += 9;
+ else if (cardSelections.card1 === 'right') guess -= 9;
+ // missing adds 0, so no change
+
+ // Card 2: left adds 3, right subtracts 3, missing adds 0
+ if (cardSelections.card2 === 'left') guess += 3;
+ else if (cardSelections.card2 === 'right') guess -= 3;
+ // missing adds 0, so no change
+
+ // Card 3: left adds 1, right subtracts 1, missing adds 0
+ if (cardSelections.card3 === 'left') guess += 1;
+ else if (cardSelections.card3 === 'right') guess -= 1;
+ // missing adds 0, so no change
+
+ // If bigger than 13, add 27
+ if (biggerThan13) guess += 27;
+
+ setCalculatedNumber(guess);
+ setStep('result');
+ };
+
+ const renderCard = (cardNumber: 1 | 2 | 3) => {
+ const cardKey = `card${cardNumber}` as keyof typeof cardData;
+ const isSelected = cardSelections[cardKey as keyof typeof cardSelections];
+
+ return (
+
+
+ Card {cardNumber}
+
+ {isSelected ? `You selected: ${isSelected === 'missing' ? 'not present' : isSelected}` : 'Choose where your number appears'}
+
+
+
+ {/* Emoji Buttons at Top */}
+
+
+
handleCardSelection(cardNumber, 'left')}
+ >
+ ⬅️
+
+
Left
+
+
+
+
handleCardSelection(cardNumber, 'missing')}
+ >
+ ❌
+
+
Not Present
+
+
+
+
handleCardSelection(cardNumber, 'right')}
+ >
+ ➡️
+
+
Right
+
+
+
+ {/* Number Boxes at Bottom */}
+
+
+
+ {cardData[cardKey].left.map(num => (
+ {num}
+ ))}
+
+
+
+
+
+ {cardData[cardKey].right.map(num => (
+ {num}
+ ))}
+
+
+
+
+
+ );
+ };
+
+ const renderFinalQuestion = () => (
+
+
+ Final Question
+
+ Is your number bigger than 13?
+
+
+
+
+ handleFinalAnswer(true)}
+ >
+ Yes, bigger than 13
+
+ handleFinalAnswer(false)}
+ >
+ No, 13 or smaller
+
+
+
+
+ );
+
+ const renderResult = () => (
+
+
+
+
+ Magic Result!
+
+
+
+
+ {calculatedNumber}
+
+
+ That's your number! 🎉
+
+
+
+ );
+
+ return (
+
+
+
+ Ternary Search Magic Trick
+
+ Think of a number between 1 and 40, then follow the magic cards to reveal your number!
+
+
+
+ {/* Step Indicator */}
+
+
+ 1. Cards
+ →
+ 2. Question
+ →
+ 3. Result
+
+
+
+ {/* Content based on step */}
+ {step === 'cards' && (
+
+
+ {renderCard(1)}
+ {renderCard(2)}
+ {renderCard(3)}
+
+
+
+
+ Continue to Final Question
+
+
+
+ )}
+
+ {step === 'final-question' && renderFinalQuestion()}
+ {step === 'result' && renderResult()}
+
+ {/* Action Buttons */}
+
+
+
+ Start Over
+
+
+
+
+
+
+ How it Works
+
+
+
+
+
+
+ How the Ternary Search Magic Trick Works
+
+
+
+
+ This trick uses the balanced ternary representation of numbers, about which you can learn more in the following video:
+
+
+ VIDEO
+
+
+
+
+
+
+ {/* Instructions */}
+
+
+ Think of a number between 1 and 40, then select which side of each card contains your number.
+
+
+ The magic will reveal your number through mathematical calculations!
+
+
+
+ {/* Social Share */}
+ {showSocialShare && (
+
+
+
+ )}
+
+
+
+ );
+};
+
+export default TernarySearchTrick;
\ No newline at end of file
diff --git a/src/pages/TernarySearchTrickGreenScreen.tsx b/src/pages/TernarySearchTrickGreenScreen.tsx
new file mode 100644
index 0000000..1875cf8
--- /dev/null
+++ b/src/pages/TernarySearchTrickGreenScreen.tsx
@@ -0,0 +1,18 @@
+import { useParams } from 'react-router-dom';
+import TernarySearchTrick from '@/components/TernarySearchTrick';
+import GreenScreenWrapper from '@/components/GreenScreenWrapper';
+
+const TernarySearchTrickGreenScreen = () => {
+ const { mode } = useParams<{ mode: 'gs-lite' | 'gs-dark' }>();
+ const greenScreenMode = mode === 'gs-dark' ? 'dark' : 'lite';
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default TernarySearchTrickGreenScreen;
\ No newline at end of file
diff --git a/src/pages/TernarySearchTrickPage.tsx b/src/pages/TernarySearchTrickPage.tsx
new file mode 100644
index 0000000..b99bd4c
--- /dev/null
+++ b/src/pages/TernarySearchTrickPage.tsx
@@ -0,0 +1,13 @@
+import TernarySearchTrick from '@/components/TernarySearchTrick';
+
+const TernarySearchTrickPage = () => {
+ return (
+
+ );
+};
+
+export default TernarySearchTrickPage;
\ No newline at end of file
diff --git a/src/pages/theme-pages/DataStructures.tsx b/src/pages/theme-pages/DataStructures.tsx
index 879a147..b879f00 100644
--- a/src/pages/theme-pages/DataStructures.tsx
+++ b/src/pages/theme-pages/DataStructures.tsx
@@ -1,14 +1,7 @@
-import Layout from "@/components/Layout";
import InteractiveGallery from "@/components/InteractiveGallery";
const DataStructures = () => {
- return (
-
-
-
-
-
- );
+ return ;
};
export default DataStructures;
\ No newline at end of file