hashirlodhi commited on
Commit
0340d96
ยท
verified ยท
1 Parent(s): 45b511b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +410 -0
app.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import plotly.graph_objects as go
3
+ import plotly.express as px
4
+ import numpy as np
5
+ import pandas as pd
6
+
7
+ def calculate_grains(square):
8
+ """Calculate grains on a specific square"""
9
+ return 2 ** (square - 1)
10
+
11
+ def calculate_total(up_to_square):
12
+ """Calculate total grains up to a specific square"""
13
+ return 2 ** up_to_square - 1
14
+
15
+ def format_number(num):
16
+ """Format large numbers with suffixes"""
17
+ if num < 1e6:
18
+ return f"{num:,.0f}"
19
+ elif num < 1e9:
20
+ return f"{num/1e6:.2f}M"
21
+ elif num < 1e12:
22
+ return f"{num/1e9:.2f}B"
23
+ elif num < 1e15:
24
+ return f"{num/1e12:.2f}T"
25
+ else:
26
+ return f"{num/1e15:.2f}Q"
27
+
28
+ def create_chessboard_heatmap(current_square):
29
+ """Create an interactive chessboard heatmap"""
30
+ # Create 8x8 grid
31
+ board = np.zeros((8, 8))
32
+ annotations = []
33
+
34
+ for i in range(8):
35
+ for j in range(8):
36
+ square_num = i * 8 + j + 1
37
+ if square_num <= current_square:
38
+ # Use log scale for better visualization
39
+ board[i, j] = np.log10(calculate_grains(square_num) + 1)
40
+
41
+ # Add square numbers as annotations
42
+ annotations.append(
43
+ dict(
44
+ x=j, y=i,
45
+ text=str(square_num),
46
+ showarrow=False,
47
+ font=dict(size=10, color='white' if board[i, j] > 5 else 'black')
48
+ )
49
+ )
50
+
51
+ fig = go.Figure(data=go.Heatmap(
52
+ z=board,
53
+ colorscale='YlOrRd',
54
+ showscale=True,
55
+ colorbar=dict(title="Logโ‚โ‚€(Grains)"),
56
+ hovertemplate='Square %{text}<br>Grains: %{customdata:,.0f}<extra></extra>',
57
+ customdata=np.array([[calculate_grains(i*8+j+1) if i*8+j+1 <= current_square else 0
58
+ for j in range(8)] for i in range(8)])
59
+ ))
60
+
61
+ fig.update_layout(
62
+ title=f"Chessboard - Up to Square {current_square}",
63
+ xaxis=dict(showticklabels=False, showgrid=False, range=[-0.5, 7.5]),
64
+ yaxis=dict(showticklabels=False, showgrid=False, range=[-0.5, 7.5]),
65
+ annotations=annotations,
66
+ width=600,
67
+ height=600,
68
+ plot_bgcolor='rgba(0,0,0,0)',
69
+ paper_bgcolor='rgba(0,0,0,0)'
70
+ )
71
+
72
+ return fig
73
+
74
+ def create_exponential_growth_chart(current_square):
75
+ """Create exponential growth visualization"""
76
+ squares = list(range(1, min(current_square + 1, 65)))
77
+ grains = [calculate_grains(s) for s in squares]
78
+
79
+ # Create two subplots: linear and log scale
80
+ fig = go.Figure()
81
+
82
+ # Add the main trace with animation effect
83
+ fig.add_trace(go.Scatter(
84
+ x=squares,
85
+ y=grains,
86
+ mode='lines+markers',
87
+ name='Grains per Square',
88
+ line=dict(color='#f59e0b', width=3),
89
+ marker=dict(size=8, color='#f59e0b'),
90
+ hovertemplate='<b>Square %{x}</b><br>Grains: %{y:,.0f}<extra></extra>'
91
+ ))
92
+
93
+ # Highlight the current square
94
+ if current_square > 1:
95
+ fig.add_trace(go.Scatter(
96
+ x=[current_square],
97
+ y=[grains[-1]],
98
+ mode='markers',
99
+ marker=dict(size=15, color='#ef4444', symbol='star'),
100
+ showlegend=False,
101
+ hovertemplate='<b>Current Square</b><br>Grains: %{y:,.0f}<extra></extra>'
102
+ ))
103
+
104
+ fig.update_layout(
105
+ title="Exponential Growth: Grains per Square",
106
+ xaxis_title="Square Number",
107
+ yaxis_title="Number of Grains",
108
+ yaxis_type="log",
109
+ hovermode='x unified',
110
+ height=500,
111
+ template='plotly_white',
112
+ font=dict(size=14),
113
+ title_font_size=20,
114
+ margin=dict(t=60, b=60, l=60, r=30)
115
+ )
116
+
117
+ return fig
118
+
119
+ def create_cumulative_chart(current_square):
120
+ """Create cumulative grains chart"""
121
+ squares = list(range(1, min(current_square + 1, 65)))
122
+ cumulative = [calculate_total(s) for s in squares]
123
+
124
+ fig = go.Figure()
125
+
126
+ fig.add_trace(go.Scatter(
127
+ x=squares,
128
+ y=cumulative,
129
+ mode='lines',
130
+ fill='tozeroy',
131
+ name='Cumulative Grains',
132
+ line=dict(color='#8b5cf6', width=3),
133
+ hovertemplate='<b>Up to Square %{x}</b><br>Total: %{y:,.0f}<extra></extra>'
134
+ ))
135
+
136
+ # Highlight the current point
137
+ if current_square > 1:
138
+ fig.add_trace(go.Scatter(
139
+ x=[current_square],
140
+ y=[cumulative[-1]],
141
+ mode='markers',
142
+ marker=dict(size=15, color='#ef4444', symbol='star'),
143
+ showlegend=False,
144
+ hovertemplate='<b>Current Total</b><br>Grains: %{y:,.0f}<extra></extra>'
145
+ ))
146
+
147
+ fig.update_layout(
148
+ title="Cumulative Total Grains",
149
+ xaxis_title="Square Number",
150
+ yaxis_title="Total Grains (Log Scale)",
151
+ yaxis_type="log",
152
+ hovermode='x unified',
153
+ height=500,
154
+ template='plotly_white',
155
+ font=dict(size=14),
156
+ title_font_size=20,
157
+ margin=dict(t=60, b=60, l=60, r=30)
158
+ )
159
+
160
+ return fig
161
+
162
+ def create_comparison_chart():
163
+ """Create comparison with real-world quantities"""
164
+ comparisons = {
165
+ 'World Population\n(8 billion)': 8e9,
166
+ 'Seconds in\n1 million years': 3.15e13,
167
+ 'Grains of sand\non Earth': 7.5e18,
168
+ 'Total Rice Grains\n(64 squares)': 1.844674407e19,
169
+ 'Stars in\nobservable universe': 1e24
170
+ }
171
+
172
+ df = pd.DataFrame({
173
+ 'Item': list(comparisons.keys()),
174
+ 'Value': list(comparisons.values())
175
+ })
176
+
177
+ # Create gradient colors
178
+ colors = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6']
179
+
180
+ fig = go.Figure(go.Bar(
181
+ x=df['Item'],
182
+ y=df['Value'],
183
+ marker_color=colors,
184
+ text=[format_number(v) for v in df['Value']],
185
+ textposition='auto',
186
+ hovertemplate='<b>%{x}</b><br>%{y:,.0e}<extra></extra>',
187
+ textfont=dict(size=14, color='white')
188
+ ))
189
+
190
+ fig.update_layout(
191
+ title="Real-World Comparisons",
192
+ yaxis_title="Quantity (Log Scale)",
193
+ yaxis_type="log",
194
+ height=500,
195
+ template='plotly_white',
196
+ font=dict(size=14),
197
+ title_font_size=20,
198
+ margin=dict(t=60, b=60, l=60, r=30)
199
+ )
200
+
201
+ return fig
202
+
203
+ def update_visualization(square_num):
204
+ """Update all visualizations based on selected square"""
205
+ current_grains = calculate_grains(square_num)
206
+ total_grains = calculate_total(square_num)
207
+
208
+ # Create statistics text with enhanced formatting
209
+ stats = f"""
210
+ <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 15px; color: white; box-shadow: 0 8px 32px rgba(0,0,0,0.2);">
211
+ <h2 style="margin-top: 0; text-align: center; font-weight: 700;">๐Ÿ“Š Current Statistics</h2>
212
+
213
+ <div style="display: flex; justify-content: space-around; margin: 20px 0;">
214
+ <div style="text-align: center;">
215
+ <div style="font-size: 1.2em; opacity: 0.9;">Square Number</div>
216
+ <div style="font-size: 2.5em; font-weight: bold;">{square_num}<span style="font-size: 1.2em;">/64</span></div>
217
+ </div>
218
+ <div style="text-align: center;">
219
+ <div style="font-size: 1.2em; opacity: 0.9;">Grains on This Square</div>
220
+ <div style="font-size: 2.5em; font-weight: bold; color: #fbbf24;">{format_number(current_grains)}</div>
221
+ </div>
222
+ <div style="text-align: center;">
223
+ <div style="font-size: 1.2em; opacity: 0.9;">Total Grains So Far</div>
224
+ <div style="font-size: 2.5em; font-weight: bold; color: #c084fc;">{format_number(total_grains)}</div>
225
+ </div>
226
+ </div>
227
+
228
+ <hr style="border: 0; border-top: 1px solid rgba(255,255,255,0.3); margin: 20px 0;">
229
+
230
+ <h3 style="text-align: center; margin-bottom: 15px;">๐ŸŒพ Real-World Context</h3>
231
+ """
232
+
233
+ # Add context based on current square
234
+ if square_num <= 10:
235
+ stats += f"<p style='text-align: center; font-size: 1.1em;'>At square {square_num}, we have {format_number(current_grains)} grains - still manageable amounts!</p>"
236
+ elif square_num <= 20:
237
+ stats += f"<p style='text-align: center; font-size: 1.1em;'>At square {square_num}, we have {format_number(current_grains)} grains per square - this is getting significant!</p>"
238
+ elif square_num <= 30:
239
+ weight_kg = total_grains * 0.00002 # ~20mg per grain
240
+ stats += f"<p style='text-align: center; font-size: 1.1em;'>Total weight so far: ~{format_number(weight_kg)} kg ({format_number(weight_kg / 1000)} metric tons!)</p>"
241
+ else:
242
+ stats += f"<p style='text-align: center; font-size: 1.1em;'>The numbers are now astronomically large! Current square alone: {format_number(current_grains)} grains</p>"
243
+
244
+ if square_num == 64:
245
+ stats += """
246
+ <div style="background: rgba(0,0,0,0.2); padding: 15px; border-radius: 10px; margin-top: 15px;">
247
+ <h3 style="text-align: center; margin-top: 0; color: #fbbf24;">๐Ÿ† Complete Board!</h3>
248
+ <p style="text-align: center; font-size: 1.2em;">
249
+ <strong>Total: 18,446,744,073,709,551,615 grains</strong><br>
250
+ Weight: ~461 billion metric tons<br>
251
+ More than 1,000 years of global rice production!
252
+ </p>
253
+ </div>
254
+ """
255
+
256
+ stats += "</div>"
257
+
258
+ # Create all charts
259
+ chessboard = create_chessboard_heatmap(square_num)
260
+ growth_chart = create_exponential_growth_chart(square_num)
261
+ cumulative_chart = create_cumulative_chart(square_num)
262
+ comparison_chart = create_comparison_chart()
263
+
264
+ return stats, chessboard, growth_chart, cumulative_chart, comparison_chart
265
+
266
+ # Create the Gradio interface with enhanced UI
267
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", secondary_hue="purple"),
268
+ title="Chess & Rice Problem",
269
+ css="""
270
+ .gradio-container {
271
+ background: linear-gradient(135deg, #1a202c 0%, #2d3748 100%);
272
+ color: white;
273
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
274
+ }
275
+ .gr-markdown h1, .gr-markdown h2, .gr-markdown h3 {
276
+ color: white;
277
+ text-align: center;
278
+ }
279
+ .gr-markdown p {
280
+ line-height: 1.6;
281
+ }
282
+ .gr-button {
283
+ border-radius: 8px;
284
+ font-weight: 600;
285
+ }
286
+ .gr-slider input[type="range"] {
287
+ height: 8px;
288
+ border-radius: 4px;
289
+ background: linear-gradient(to right, #f59e0b, #8b5cf6);
290
+ }
291
+ .gr-plot {
292
+ border-radius: 12px;
293
+ overflow: hidden;
294
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3);
295
+ }
296
+ .gr-row {
297
+ margin-bottom: 20px;
298
+ }
299
+ .gr-column {
300
+ display: flex;
301
+ justify-content: center;
302
+ }
303
+ .footer {
304
+ text-align: center;
305
+ padding: 20px;
306
+ color: rgba(255,255,255,0.7);
307
+ font-size: 0.9em;
308
+ }
309
+ """) as app:
310
+
311
+ gr.Markdown("""
312
+ # ๐ŸŽฒ The Chess and Rice Grains Problem
313
+ ## Exploring the Power of Exponential Growth
314
+
315
+ ### ๐Ÿ“– The Legend
316
+ According to legend, when the inventor of chess presented the game to an ancient king, the king was so pleased
317
+ that he offered the inventor any reward. The wise inventor made a seemingly humble request:
318
+
319
+ - Place **1 grain of rice** on the first square of a chessboard
320
+ - Place **2 grains** on the second square
321
+ - Place **4 grains** on the third square
322
+ - **Double the amount** on each subsequent square for all 64 squares
323
+
324
+ The king agreed immediately, thinking it was a modest request. But was it?
325
+
326
+ ### ๐Ÿงฎ The Mathematics
327
+ This problem demonstrates **exponential growth** with base 2:
328
+ - Grains on square n: **2<sup>(n-1)</sup>**
329
+ - Total grains up to square n: **2<sup>n</sup> - 1**
330
+ - Complete board (64 squares): **2<sup>64</sup> - 1 = 18,446,744,073,709,551,615**
331
+
332
+ Use the slider below to explore how quickly the numbers grow!
333
+ """)
334
+
335
+ with gr.Row():
336
+ square_slider = gr.Slider(
337
+ minimum=1,
338
+ maximum=64,
339
+ value=1,
340
+ step=1,
341
+ label="Select Square Number",
342
+ info="Move the slider to see how grains accumulate",
343
+ interactive=True
344
+ )
345
+
346
+ with gr.Row():
347
+ stats_output = gr.HTML()
348
+
349
+ with gr.Row():
350
+ chessboard_plot = gr.Plot(label="Interactive Chessboard", show_label=False)
351
+
352
+ with gr.Row(equal_height=True):
353
+ with gr.Column():
354
+ growth_plot = gr.Plot(label="Exponential Growth", show_label=False)
355
+ with gr.Column():
356
+ cumulative_plot = gr.Plot(label="Cumulative Total", show_label=False)
357
+
358
+ with gr.Row():
359
+ comparison_plot = gr.Plot(label="Real-World Comparisons", show_label=False)
360
+
361
+ gr.Markdown("""
362
+ ---
363
+ ### ๐Ÿ”ฌ Key Insights
364
+
365
+ 1. **Exponential Growth is Deceptive**: The first half of the board (32 squares) contains less than 0.00001% of the total grains!
366
+
367
+ 2. **The Power of Doubling**: Each square has more grains than all previous squares combined, plus one.
368
+ - Mathematical proof: 2<sup>n</sup> = (2<sup>n</sup> - 1) + 1
369
+
370
+ 3. **Real-World Scale**:
371
+ - The total grains would weigh approximately **461 billion metric tons**
372
+ - This exceeds **1,000 years** of current global rice production
373
+ - If each grain is 6mm long, they would stretch over **116 trillion kilometers** (about 777 AU)
374
+
375
+ 4. **Computer Science**: This problem illustrates why 64-bit computing exists - 2<sup>64</sup> combinations!
376
+
377
+ ### ๐ŸŽฏ Formula Summary
378
+
379
+ | Concept | Formula | Example (Square 10) |
380
+ |---------|---------|---------------------|
381
+ | Grains on square n | 2<sup>(n-1)</sup> | 2<sup>9</sup> = 512 |
382
+ | Total up to square n | 2<sup>n</sup> - 1 | 2<sup>10</sup> - 1 = 1,023 |
383
+ | Doubling pattern | Each square = All previous + 1 | 512 = 511 + 1 |
384
+
385
+ ### ๐Ÿ’ก Applications
386
+ - **Computing**: Understanding memory and storage (bytes, bits)
387
+ - **Finance**: Compound interest and investment growth
388
+ - **Biology**: Bacterial reproduction and population growth
389
+ - **Virology**: Disease spread modeling
390
+ - **Physics**: Radioactive decay (inverse exponential)
391
+ """)
392
+
393
+ # Set up interactivity with animation effect
394
+ square_slider.change(
395
+ fn=update_visualization,
396
+ inputs=[square_slider],
397
+ outputs=[stats_output, chessboard_plot, growth_plot, cumulative_plot, comparison_plot],
398
+ show_progress="minimal"
399
+ )
400
+
401
+ # Initialize with square 1
402
+ app.load(
403
+ fn=update_visualization,
404
+ inputs=[square_slider],
405
+ outputs=[stats_output, chessboard_plot, growth_plot, cumulative_plot, comparison_plot]
406
+ )
407
+
408
+ # Launch the app
409
+ if __name__ == "__main__":
410
+ app.launch()