diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/contest.mdx b/src/fibonacci-secondarie/2023-terza-fase/contest/contest.mdx new file mode 100644 index 0000000..8f626ce --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/contest.mdx @@ -0,0 +1,15 @@ +import { S1Cioccolato } from "problemset"; +import { S2Montagna } from "problemset"; +import { S3Calcolatrice } from "problemset"; +import { S4Superbunny } from "problemset"; + + + +
+ + + + +
+ +
diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/header.md b/src/fibonacci-secondarie/2023-terza-fase/contest/header.md new file mode 100644 index 0000000..397759a --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/header.md @@ -0,0 +1,19 @@ +# Giochi di Fibonacci 2023/2024 + +## Fase finale - Scuole secondarie + +Questa prova contiene _4 domande_ da risolvere in _3 ore_. +Tutte le domande sono di **programmazione** tramite blocchi, e sono ordinate per difficoltà crescente. +**Attento che la difficoltà è soggettiva!** Se stai passando tanto tempo cercando di risolvere una domanda, prova a passare ad altre domande e altre categorie! + +## Punteggio + +Tutte le domande sono a _blocchi_ e richiedono di scrivere un singolo programma a blocchi, che viene valutato su 10 diversi livelli. +Per ciascuna domanda e per ciascun livello, Il punteggio che puoi ottenere è: + +- 5 punti se il programma produce la risposta _corretta_; +- 0 punti se il programma produce una risposta _sbagliata_. + +Quindi ogni domanda a blocchi può valere fino a 50 punti in totale. + +In ogni domanda a blocchi, i primi 5 livelli vengono anche visualizzati graficamente, mentre gli ultimi 5 livelli non vengono visualizzati. \ No newline at end of file diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies0.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies0.asy new file mode 100644 index 0000000..fbdd963 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies0.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(bunny.drawing(0.85, bunny.allie_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies1.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies1.asy new file mode 100644 index 0000000..4833c3a --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies1.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(bunny.drawing(0.85, bunny.bunny_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies2.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies2.asy new file mode 100644 index 0000000..7f2d9f7 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies2.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(bunny.drawing(0.85, bunny.carol_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies3.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies3.asy new file mode 100644 index 0000000..d1cb8b2 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunnies3.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(bunny.drawing(0.85, bunny.tiptap_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunny.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunny.asy new file mode 100644 index 0000000..9d0a185 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/bunny.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(reflect((2, 1), (2, 0))*bunny.drawing(0.85, bunny.tiptap_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/chocolate.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/chocolate.asy new file mode 100644 index 0000000..bcbaf4b --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/asy/chocolate.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/chocolate.asy" as chocolate; + +add(chocolate.drawing()); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/customBlocks.yaml b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/customBlocks.yaml new file mode 100644 index 0000000..fef6502 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/customBlocks.yaml @@ -0,0 +1,95 @@ +- type: start + message0: inizia qui + nextStatement: null + colour: 20 + tooltip: L'esecuzione inizia da qui + helpUrl: "" + maxInstances: 1 + js: "" + +- type: larghezza + message0: larghezza + output: Number + colour: 20 + tooltip: larghezza della tavoletta rimasta + helpUrl: "" + js: + - hiddenState.N + - ORDER_MEMBER + +- type: altezza + message0: altezza + output: Number + colour: 20 + tooltip: altezza della tavoletta rimasta + helpUrl: "" + js: + - hiddenState.M + - ORDER_MEMBER + +- type: compagni + message0: compagni + output: Number + colour: 20 + tooltip: numero di compagni rimasti + helpUrl: "" + js: + - hiddenState.K + - ORDER_MEMBER + +- type: spezza in orizzontale + message0: spezza %1 quadratini in orizzontale + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + previousStatement: null + nextStatement: null + colour: 20 + tooltip: spezza x quadratini in orizzontale + helpUrl: "" + js: |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i <= 0 || Math.floor(i) != i) exit(false, "numero di righe " + i + " non valido"); + if (i > hiddenState.M) exit(false, "non ci sono " + i + " righe"); + hiddenState.M -= i; + hiddenState.K -= 1; + hiddenState.cuts.push(i); + })(%0); + +- type: spezza in verticale + message0: spezza %1 quadratini in verticale + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + previousStatement: null + nextStatement: null + colour: 20 + tooltip: spezza x quadratini in verticale + helpUrl: "" + js: |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i <= 0 || Math.floor(i) != i) exit(false, "numero di colonne " + i + " non valido"); + if (i > hiddenState.N) exit(false, "non ci sono " + i + " colonne"); + hiddenState.N -= i; + hiddenState.K -= 1; + hiddenState.cuts.push(-i); + })(%0); + +- type: termina + message0: termina + previousStatement: null + colour: 20 + tooltip: termina il procedimento + helpUrl: "" + js: | + if (hiddenState.K > 0) + exit(false, "ci sono ancora compagni che vogliono cioccolato"); + if (hiddenState.N*hiddenState.M < hiddenState.sol) + exit(false, "potevi tenerti più cioccolato"); + exit(true, "hai distribuito bene il cioccolato, complimenti!"); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/initialBlocks.json b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/initialBlocks.json new file mode 100644 index 0000000..64bd836 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/initialBlocks.json @@ -0,0 +1,14 @@ +{ + "blocks": { + "languageVersion": 0, + "blocks": [ + { + "type": "start", + "id": "y=zq)Uya2A/{vyOtN[i6", + "x": 61, + "y": 81 + } + ] + }, + "variables": [] +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/lorenzo.jpg b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/lorenzo.jpg new file mode 100644 index 0000000..96aab59 Binary files /dev/null and b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/lorenzo.jpg differ diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/question.mdx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/question.mdx new file mode 100644 index 0000000..4cab150 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/question.mdx @@ -0,0 +1,42 @@ +import initialBlocks from "./initialBlocks.json"; +import customBlocks from "./customBlocks.yaml"; +import testcases from "./testcases.py"; +import Visualizer from "./visualizer.jsx"; + +Tip-Tap adora il cioccolato, e allora si è comprato una tavoletta di cioccolato fatta di $N \times M$ quadratini. +Anche i $K$ suoi compagni di fattoria vorrebbero mangiare il cioccolato, e Tip-Tap è troppo buono per non dargliene! +Quindi per $K$ volte spezza la tavoletta in due parti rettangolari, non necessariamente uguali, e dà una delle due ad uno dei suoi $K$ compagni tenendo infine l'ultimo pezzo per sè. + +!["La tavoletta di Tip-Tap"](lorenzo.jpg "Il cioccolato non è mai troppo!") + +La tavoletta può essere spezzata solo lungo i bordi dei quadratini, in orizzontale o verticale, in modo tale da non dividere nessun quadratino in due. +Inoltre una volta spezzata una parte, quella viene subito presa e mangiata da un amico senza dargli la possibilità di spezzarla ulteriormente. +Tip-Tap vorrebbe sapere come spezzare la tavoletta $K$ volte in modo che gli rimangano il maggior numero possibile di quadratini. Puoi aiutarlo? + +Puoi usare questi blocchi: + +- `larghezza`: la larghezza attuale della tavoletta. +- `altezza`: l'altezza attuale della tavoletta. +- `compagni`: il numero di compagni che ancora chiedono del cioccolato. +- `spezza x quadratini in orizzontale`: spezza la tavoletta in orizzontale, lasciando $x$ file ad un compagno. +- `spezza x quadratini in verticale`: spezza la tavoletta in verticale, lasciando $x$ colonne ad un compagno. +- `termina`: mangia il cioccolato rimasto. + +Aiuta Tip-Tap a spezzare la tavoletta $K$ volte, in modo gli rimanga il maggior numero possibile di quadratini! + + + +> Un possibile programma corretto è il seguente: +> +> ![soluzione](sol.png) +> +> Secondo questo programma, per ognuno dei compagni di Tip-Tap, il protagonista +> controlla se la tavoletta è più larga o più alta, e gli passa una singola fila +> o colonna a seconda di quale delle due è più piccola. In questo modo, si +> assicura che alla fine gli rimanga più cioccolato possibile. diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/sol.png b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/sol.png new file mode 100644 index 0000000..873fbce Binary files /dev/null and b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/sol.png differ diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/testcases.py b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/testcases.py new file mode 100644 index 0000000..8ac8d71 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/testcases.py @@ -0,0 +1,57 @@ +from random import randint, seed +import json +import math + +seed(42) + +L = [2, 5, 10, 10, 10, 90, 900, 900, 900, 900] +U = [3, 10, 20, 20, 20, 100, 1000, 1000, 1000, 1000] +type = [0, 1, 2, 3, 0, 3, 0, 2, 0, 4] + +params = [L, U, type] + +def solve(n, m, k): + if n > m: + n, m = m, n + d = min(k, m - n) + k -= d + m -= d + n -= k // 2 + m -= k // 2 + k % 2 + return n*m + +def generate(L, U, type): + args = set(locals()) | set(['args']) + + # base generator + if type == 1: + # M = 1 + N = randint(L, U) + M = 1 + elif type == 2: + #quadrato + N = M = randint(L, U) + elif type == 3: + #rettangolo stretto e allungato + M = randint(L, U) + N = randint(1, L) + else: + #generico + N = randint(L, U) + M = randint(L, U) + + if type == 4: + K = randint(max(N+M-5, 1), N+M-2) + else: + K = randint(1, N+M-2) + + # additional state for visualizer + sol = solve(N, M, K) + cuts = [] + + return {k:v for k,v in locals().items() if k not in args} + +testcases = [] +for args in zip(*params): + testcases.append(generate(*args)) +print(json.dumps(list(testcases))) diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/visualizer.jsx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/visualizer.jsx new file mode 100644 index 0000000..b8d753d --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-1-cioccolato/visualizer.jsx @@ -0,0 +1,62 @@ +import React from "react"; +import { range } from "lodash-es"; + +import { Canvas, Sprite, Rectangle, Variables } from "~/utils/visualizer"; + +import bunny from "./asy/bunny.asy?w=66"; +import chocolate from "./asy/chocolate.asy?w=25"; + +const bunnies = import.meta.glob("./asy/bunnies*.asy", { + eager: true, + import: "default", + query: { w: 50 }, +}); + +export default function Visualizer({ variables }) { + const { blocklyVariables, hiddenState } = variables; + if (!hiddenState) return; + + var blocks = []; + var xoffs = 1.5; + var yoffs = 9; + var sep = 0.15; + + function chocblock(N0, N, M0, M, name="cioc") { + for (var i=N0; i) + } + + var N = hiddenState.N; + var M = hiddenState.M; + if (N <= 20 && M <= 20) { + chocblock(0, N, 0, M); + for (var i=hiddenState.cuts.length-1; i>=0; --i) { + var c = hiddenState.cuts[i]; + if (c > 0) { + yoffs -= sep; + chocblock(0, N, M, M+c); + M += c; + } else { + xoffs += sep; + chocblock(N, N-c, 0, M); + N -= c; + } + } + } + + var len = Object.keys(bunnies).length; + + return ( + <> + + + {range(N <= 20 && M <= 20 ? hiddenState.K : 0).map((i) => { + return + })} + {blocks} + + + + ); +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/bunny.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/bunny.asy new file mode 100644 index 0000000..ec63788 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/bunny.asy @@ -0,0 +1,14 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +filldraw((2,-1) -- (2.5,0) -- (6,0) -- (5.5,-1) -- cycle, heavyblue*0.5 + lightgray*0.5, blue+3); +add(shift(-0.7,0.3)*reflect((2, 1), (2, 0))*bunny.drawing(0.85, bunny.bunny_col)); +add(shift(1.2,0.6)*reflect((2, 1), (2, 0))*bunny.drawing(0.85, bunny.tiptap_col)); +add(shift(0.5,0)*reflect((2, 1), (2, 0))*bunny.drawing(0.85, bunny.carol_col)); +filldraw((2,-1) -- (5.5,-1) -- (6, -2) -- (2, -2) -- cycle, heavyblue, blue+3); +filldraw((6,0) -- (5.5,-1) -- (6, -2) -- (6.5,-1) -- cycle, darkblue, blue+3); +for (int i=0; i<2; ++i) { + filldraw(circle((3+2*i,-2), 0.7), gray, black+3); + filldraw(circle((3+2*i,-2), 0.2), mediumgray, black+2); +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/leftri.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/leftri.asy new file mode 100644 index 0000000..40efdfe --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/leftri.asy @@ -0,0 +1,9 @@ +unitsize(1cm); + +pen lightcol = rgb("9e6b5a"); +pen darkcol = brown+2; + +path bord = (0,0) {dir(10)}..{dir(30)} (1,1); + +fill(bord -- (1,0) -- cycle, lightcol); +fill((0,0) {dir(0)}..{dir(35)} (1,1) -- reverse(bord) -- cycle, darkcol); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/leftsnow.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/leftsnow.asy new file mode 100644 index 0000000..9e4532e --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/leftsnow.asy @@ -0,0 +1,10 @@ +unitsize(1cm); + +pen lightcol = rgb("9e6b5a"); +pen darkcol = brown+2; + +path bord = (0,0) {dir(60)}..{E} (1,1); + +fill(bord -- (1,0) -- cycle, lightcol); +fill(point(bord, 0.2) {E}..{dir(50)} (1,0.45) -- (1,1) -- subpath(bord, 1, 0.2) -- cycle, palegray); +fill((0,0) {dir(55)}..{dir(5)} (1,1) -- reverse(bord) -- cycle, darkcol); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/offcharge.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/offcharge.asy new file mode 100644 index 0000000..7f40816 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/offcharge.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/charger.asy" as charger; + +add(charger.drawing()); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/oncharge.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/oncharge.asy new file mode 100644 index 0000000..d69ce48 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/oncharge.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/charger.asy" as charger; + +add(charger.drawing(1, lightyellow, green)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/rightri.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/rightri.asy new file mode 100644 index 0000000..fd827f1 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/rightri.asy @@ -0,0 +1,9 @@ +unitsize(1cm); + +pen lightcol = rgb("9e6b5a"); +pen darkcol = brown+2; + +path bord = (0,1) {dir(-30)}..{dir(-10)} (1,0); + +fill((0,0) -- bord -- cycle, lightcol); +fill((0,1) {dir(-35)}..{dir(0)} (1,0) -- reverse(bord) -- cycle, darkcol); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/rightsnow.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/rightsnow.asy new file mode 100644 index 0000000..a8bf648 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/rightsnow.asy @@ -0,0 +1,10 @@ +unitsize(1cm); + +pen lightcol = rgb("9e6b5a"); +pen darkcol = brown+2; + +path bord = (0,1) {E}..{dir(-60)} (1,0); + +fill((0,0) -- bord -- cycle, lightcol); +fill((0,0.45) {dir(10)}.. subpath(bord, 0.4, 0) -- cycle, palegray); +fill((0,1) {dir(-5)}..{dir(-55)} (1,0) -- reverse(bord) -- cycle, darkcol); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/square.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/square.asy new file mode 100644 index 0000000..086e3eb --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/square.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +pen lightcol = rgb("9e6b5a"); + +fill((0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle, lightcol); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/squarecap.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/squarecap.asy new file mode 100644 index 0000000..1f5e128 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/asy/squarecap.asy @@ -0,0 +1,7 @@ +unitsize(1cm); + +pen lightcol = rgb("9e6b5a"); +pen darkcol = brown+2; + +fill((0,0) -- (0,1) -- (1,1) -- (1,0) -- cycle, lightcol); +fill((0,1) {dir(-15)}..{dir(15)} (1,1) -- cycle, darkcol); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/customBlocks.yaml b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/customBlocks.yaml new file mode 100644 index 0000000..3b8791c --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/customBlocks.yaml @@ -0,0 +1,117 @@ +- type: start + message0: inizia qui + nextStatement: null + colour: 20 + tooltip: L'esecuzione inizia da qui + helpUrl: "" + maxInstances: 1 + js: "" + +- type: N + message0: N + output: Number + colour: 20 + tooltip: numero di colonnine lungo il percorso + helpUrl: "" + js: + - hiddenState.N + - ORDER_MEMBER + +- type: energia + message0: energia + output: Number + colour: 20 + tooltip: energia rimasta + helpUrl: "" + js: + - hiddenState.energy + - ORDER_MEMBER + +- type: altitudine della colonnina + message0: altitudine della colonnina %1 + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + output: Number + colour: 20 + tooltip: altitudine della colonnina i-esima + helpUrl: "" + js: + - |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "la colonnina " + i + " non esiste"); + return hiddenState.H[i-1]; + })(%0) + - ORDER_FUNCTION_CALL + +- type: avanza + message0: avanza + previousStatement: null + nextStatement: null + colour: 20 + tooltip: avanza fino alla prossima colonnina + helpUrl: "" + js: | + hiddenState.charging = false; + if (hiddenState.posx == hiddenState.N-1) + exit(false, "sei già arrivato alla fine"); + delta = hiddenState.H[hiddenState.posx+1] - hiddenState.H[hiddenState.posx]; + hiddenState.rot = Math.atan2(hiddenState.scale * delta, 1); + pause(1); + if (hiddenState.energy >= delta) { + hiddenState.posx += 1; + hiddenState.posy += hiddenState.scale * delta; + hiddenState.energy -= delta; + } else { + hiddenState.posx += hiddenState.energy / delta; + hiddenState.posy += hiddenState.scale * hiddenState.energy; + hiddenState.energy = 0; + exit(false, "hai finito l'energia prima di arrivare"); + } + pause(1); + if (hiddenState.posx < hiddenState.N-1) + hiddenState.rot = ( + Math.atan2(hiddenState.scale * (hiddenState.H[hiddenState.posx+1] - hiddenState.H[hiddenState.posx]), 1) + + Math.atan2(hiddenState.scale * (hiddenState.H[hiddenState.posx] - hiddenState.H[hiddenState.posx-1]), 1) + )/2; + else hiddenState.rot = 0; + +- type: ricarica + message0: ricarica per %1 minuti + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + previousStatement: null + nextStatement: null + colour: 20 + tooltip: ricarica per x minuti + helpUrl: "" + js: |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 0 || i > 1000000 || Math.floor(i) != i) + exit(false, "numero di minuti " + i + " non valido"); + hiddenState.time += i; + hiddenState.energy += i; + hiddenState.charging = true; + })(%0); + +- type: termina + message0: termina + previousStatement: null + colour: 20 + tooltip: termina il procedimento + helpUrl: "" + js: | + hiddenState.charging = false; + if (hiddenState.pos < hiddenState.N-1) + exit(false, "non sei arrivato alla fine"); + if (hiddenState.time > hiddenState.sol) + exit(false, "potevi aspettare meno alle colonnine"); + exit(true, "sei arrivato in fretta, complimenti!"); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/initialBlocks.json b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/initialBlocks.json new file mode 100644 index 0000000..64bd836 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/initialBlocks.json @@ -0,0 +1,14 @@ +{ + "blocks": { + "languageVersion": 0, + "blocks": [ + { + "type": "start", + "id": "y=zq)Uya2A/{vyOtN[i6", + "x": 61, + "y": 81 + } + ] + }, + "variables": [] +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/question.mdx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/question.mdx new file mode 100644 index 0000000..7395d1c --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/question.mdx @@ -0,0 +1,50 @@ +import initialBlocks from "./initialBlocks.json"; +import customBlocks from "./customBlocks.yaml"; +import testcases from "./testcases.py"; +import Visualizer from "./visualizer.jsx"; + +I conigli della fattoria Fibonacci hanno appena comprato una nuova efficentissima macchina elettrica! + +Non vedono l'ora di provarla, quindi organizzano un viaggio di prova sulle montagne vicine. Il tragitto che vogliono fare è fatto da tratti in salita e tratti in discesa. +Lungo il percorso ci sono $N$ colonnine di ricarica dove potersi fermare, a diverse altezze. La macchina **usa** un'unità di energia **salendo** di $1$ metro di altitudine, +mentre **guadagna** un'unità di energia **scendendo** di $1$ metro di altitudine, e non le serve energia per avanzare nei tratti in piano. +Purtroppo la macchina parte senza energia, e per ricaricarsi può attendere **un minuto** ad una delle colonnine per ogni unità di energia che vuole ottenere in quel momento. + +Puoi usare questi blocchi: + +- `N`: la lunghezza $N$ del percorso. +- `energia`: la quantità corrente di energia. +- `altitudine della colonnina i`: l'altitudine della colonnina di ricarica $i$-esima nel percorso. +- `avanza`: prosegui il viaggio fino alla prossima colonnina, se hai abbastanza energia. +- `ricarica per x minuti`: attendi $x$ minuti ad una colonnina per ricaricare $x$ unità di energia. +- `termina`: spegni la macchina. + +I conigli partono dalla colonnina 1, e devono arrivare alla colonnina $N$. +Organizza il viaggio sulle montagne, evitando che la macchina si fermi prima di arrivare! + + + +> Un possibile programma corretto è il seguente: +> +> ![soluzione](sol1.png) +> +> Secondo questo programma, per ognuna delle colonnine a partire dalla seconda, si controlla +> se c'è abbastanza energia rimasta per coprire la differenza di altezza tra la prossima +> colonnina $i$ e quella corrente $i-1$. Se non è sufficiente, ci si ricarica +> alla colonnina per la quantità di minuti minima indispensabile. Poi in ogni +> caso si procede alla colonnina successiva. +> +> Un altro possibile approccio è il seguente: +> +> ![soluzione](sol2.png) +> +> Secondo questo programma, prima si calcola la massima altezza di una qualunque colonnina +> lungo il percorso. A questo punto, ci si ricarica una singola volta della quantità di energia +> necessaria per salire dall'altezza iniziale fino all'altezza massima. A questo punto c'è +> abbastanza energia per procedere fino alla fine senza fermarsi. diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/sol1.png b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/sol1.png new file mode 100644 index 0000000..c88d8e8 Binary files /dev/null and b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/sol1.png differ diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/sol2.png b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/sol2.png new file mode 100644 index 0000000..2fecb2c Binary files /dev/null and b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/sol2.png differ diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/testcases.py b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/testcases.py new file mode 100644 index 0000000..f33f1e3 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/testcases.py @@ -0,0 +1,52 @@ +from random import randint, seed +import json +import math +seed(0) + +N = [5, 7, 10, 20, 30, 100, 1000, 1000, 1000, 1000] +INF = [8, 10, 20, 20, 30, 10000, 10000, 10000, 10000, 10000] +type = [2, 2, 2, 2, 2, 2, 0, 2, 1, 2] + +params = [N, INF, type] + +def generate(n, INF, type): + args = set(locals()) | set(['args']) + + # base generator + N = n + H = [] + if type == 0: + H.append(randint(1, 100)) + for i in range(1, N): + H.append(H[i-1] + randint(0, 10) + 1) + elif type == 1: + for i in range(N): + if i%2: + H.append(randint(0, 100)) + else: + H.append(randint(INF - 100, INF)) + else: + H.append(0) + H.append(randint(2, INF//2)) + H.append(H[1] - randint(1, 2)) + H.append(randint(INF//2+1, INF-1)) + H.append(H[3] + 1) + for i in range(5, N): + H.append(randint(0, INF)) + + # additional state for visualizer + scale = 10 / max(H) + rot = 0 + posx = 0 + posy = H[0] + time = 0 + energy = 0 + sol = max(H) - H[0] + charging = False + + return {k:v for k,v in locals().items() if k not in args} + +testcases = [] +for args in zip(*params): + testcases.append(generate(*args)) +print(json.dumps(list(testcases))) diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/visualizer.jsx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/visualizer.jsx new file mode 100644 index 0000000..f77a1fa --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-2-montagna/visualizer.jsx @@ -0,0 +1,124 @@ +import React from "react"; +import { range } from "lodash-es"; + +import { Canvas, Sprite, Rectangle, Variables } from "~/utils/visualizer"; + +import bunny from "./asy/bunny.asy?w=50"; +import leftri from "./asy/leftri.asy?w=40"; +import rightri from "./asy/rightri.asy?w=40"; +import leftsnow from "./asy/leftsnow.asy?w=40"; +import rightsnow from "./asy/rightsnow.asy?w=40"; +import square from "./asy/square.asy?w=40"; +import squarecap from "./asy/squarecap.asy?w=40"; +import offcharge from "./asy/offcharge.asy?w=20"; +import oncharge from "./asy/oncharge.asy?w=20"; + +export default function Visualizer({ variables }) { + const { blocklyVariables, hiddenState } = variables; + if (!hiddenState) return; + + var dry = 0.6; + var dy = 0; + var mountains = []; + var eps = 0.03; + var de = eps; + var h = hiddenState.H[0] * hiddenState.scale - 1; + if (hiddenState.N <= 30) { + mountains.push( + + ); + mountains.push( + + ); + for (var i=0; i + ); + if (hiddenState.H[i] < hiddenState.H[i+1]) { + var delta = (hiddenState.H[i+1] - hiddenState.H[i]) * hiddenState.scale; + var snow = 0; + var cap = i < hiddenState.N-2 && hiddenState.H[i+1] > hiddenState.H[i+2]; + if (cap) { + var bounce = (hiddenState.H[i+1] - hiddenState.H[i+2]) * hiddenState.scale; + if (bounce >= delta) snow = 1; + else snow = bounce / delta; + } + if (snow > 0 && snow < 1) { + mountains.push( + + ); + } + if (snow > 0) + mountains.push( + + ); + if (snow < 1) + mountains.push( + + ); + } else if (hiddenState.H[i] > hiddenState.H[i+1]) { + var delta = (hiddenState.H[i] - hiddenState.H[i+1]) * hiddenState.scale; + var snow = 0; + var cap = i > 0 && hiddenState.H[i] > hiddenState.H[i-1]; + if (cap) { + var bounce = (hiddenState.H[i] - hiddenState.H[i-1]) * hiddenState.scale; + if (bounce >= delta) snow = 1; + else snow = bounce / delta; + } + if (snow > 0 && snow < 1) { + mountains.push( + + ); + } + if (snow > 0) + mountains.push( + + ); + if (snow < 1) + mountains.push( + + ); + } else { + mountains.push( + + ); + } + } + h = hiddenState.H[hiddenState.N-1] * hiddenState.scale - 1; + mountains.push( + + ); + mountains.push( + + ); + } + + function pos(i) { + if (i == 0 || i == hiddenState.N-1) return hiddenState.H[i]; + return (hiddenState.H[i-1] + hiddenState.H[i+1])*0.025 + hiddenState.H[i] * 0.95; + } + + var bx = -0.6; + var by = dy+8.7; + var br = 0; + if (hiddenState.N <= 30) { + bx = hiddenState.posx-0.6 + dry*Math.cos(1.5707963267948966+hiddenState.rot); + by = dy+8.7-(hiddenState.posx % 1 == 0 ? pos(hiddenState.posx) : hiddenState.posy)*hiddenState.scale + dry - dry*Math.sin(1.5707963267948966+hiddenState.rot); + br = -hiddenState.rot/6.283185307179586; + } + + return ( + <> + + {mountains} + + {range(hiddenState.N <= 30 ? hiddenState.N : 0).map((i) => ( + + ))} + + + + ); +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/asy/bunny.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/asy/bunny.asy new file mode 100644 index 0000000..6e2b799 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/asy/bunny.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(reflect((2, 1), (2, 0))*bunny.drawing(0.85, bunny.carol_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/calcolatrice.svg b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/calcolatrice.svg new file mode 100644 index 0000000..07259bc --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/calcolatrice.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/customBlocks.yaml b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/customBlocks.yaml new file mode 100644 index 0000000..ea473cd --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/customBlocks.yaml @@ -0,0 +1,38 @@ +- type: start + message0: inizia qui + nextStatement: null + colour: 20 + tooltip: L'esecuzione inizia da qui + helpUrl: "" + maxInstances: 1 + js: "" + +- type: N + message0: N + output: Number + colour: 20 + tooltip: il numero da raggiungere + helpUrl: "" + js: + - hiddenState.N + - ORDER_MEMBER + +- type: termina + message0: termina in %1 operazioni + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + previousStatement: null + colour: 20 + tooltip: termina in x operazioni + helpUrl: "" + js: |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 0 || Math.floor(i) != i) exit(false, "numero di operazioni " + i + " non valido"); + if (i > hiddenState.sol) exit(false, "potevi fare meno di " + i + " operazioni"); + if (i < hiddenState.sol) exit(false, "non si può ottenere " + hiddenState.N + " con " + i + " operazioni"); + exit(true, i + " è il numero minimo di operazioni, complimenti!"); + })(%0); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/initialBlocks.json b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/initialBlocks.json new file mode 100644 index 0000000..64bd836 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/initialBlocks.json @@ -0,0 +1,14 @@ +{ + "blocks": { + "languageVersion": 0, + "blocks": [ + { + "type": "start", + "id": "y=zq)Uya2A/{vyOtN[i6", + "x": 61, + "y": 81 + } + ] + }, + "variables": [] +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/question.mdx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/question.mdx new file mode 100644 index 0000000..008f983 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/question.mdx @@ -0,0 +1,53 @@ +import initialBlocks from "./initialBlocks.json"; +import customBlocks from "./customBlocks.yaml"; +import testcases from "./testcases.py"; +import Visualizer from "./visualizer.jsx"; + +Carol ha fatto cadere la sua calcolatrice, e ora non funziona più come dovrebbe! +Gli unici tasti funzionanti sono il $-$, il $\times$, l'$1$ e il $2$. +Per utilizzare la calcolatrice è costretta a partire dal numero $1$ o dal numero $2$ (premendo il tasto corrispondente) e applicare zero o più volte una delle $4$ possibili operazioni funzionanti: + +- sottrarre $1$ +- sottrarre $2$ +- moltiplicare per $1$ +- moltiplicare per $2$ + +Per fare uno scherzo ai suoi amici, vorrebbe raggiungere sulla calcolatrice il numero $N$. Quante operazioni deve fare al minimo per farlo? + +_**Nota:** premere il tasto $1$ o $2$ all'inizio conta come un'operazione, inoltre la calcolatrice è danneggiata quindi Carol è costretta a partire sempre da $1$ o $2$ (**non** può ad esempio premere $2$ e poi $1$ per partire dal numero $21$) e le uniche operazioni ammesse sono quelle precedentemente elencate (**non** può per esempio moltiplicare o sottrarre $12$ o $21$)._ + +Puoi usare questi blocchi: + +- `N`: il numero $N$ che vuole raggiungere. +- `termina in x operazioni`: riporta che è possibile raggiungere il numero $N$ in $x$ operazioni. + +_**Attenzione:** non ti viene richiesto di ricostruire le operazioni da fare, basta che calcoli il numero di operazioni necessario!_ + + + +> Un possibile programma corretto è il seguente: +> +> ![soluzione](sol.png) +> +> L'idea di questa soluzione è di ragionare al contrario, partendo dal numero +> che si vuole raggiungere e tornando indietro con le operazioni inverse. Per +> esempio, se vogliamo raggiungere il numero 5, ci chiediamo quale numero potrebbe +> essere l'ultimo che raggiungiamo prima di arrivare al 5. Visto che 5 è dispari, +> non può essere che l'ultima operazione sia un raddoppio, e moltiplicare per 1 +> non è mai utile. Quindi il numero prima potrebbe essere o il 6 (da cui sottraendo +> 1 si arriva al 5), oppure il 7 (da cui sottraendo 2 si arriva al 5). Il 7 però +> non sembra conveniente, perché essendo dispari ci si può arrivare solo da un'altro +> numero ancora più grande (8 o 9), il che ci allontana dal nostro obiettivo. +> Si può quindi mostrare che quando dobbiamo raggiungere un valore $n$ dispari, +> la cosa migliore è raggiungere prima $n+1$. Similmente, quando dobbiamo raggiungere +> un valore $n$ pari, la cosa migliore è raggiungere prima $n/2$. Ripetiamo quindi +> questo procedimento a ritroso a partire dal nostro obiettivo $N$, fino a che +> non raggiungiamo 1 o 2, che sono numeri che possiamo direttamente scrivere +> sulla nostra calcolatrice. Nel frattempo contiamo quante operazioni stiamo +> facendo nella variabile risposta, risolvendo il quesito! diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/sol.png b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/sol.png new file mode 100644 index 0000000..4da2381 Binary files /dev/null and b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/sol.png differ diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/testcases.py b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/testcases.py new file mode 100644 index 0000000..6d0a4c3 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/testcases.py @@ -0,0 +1,36 @@ +import random +import json +import math +random.seed(0) + +MIN = [2, 2, 2, 500, 1e4-500, 1e6-500, 1e7, 1e11, 1e15-1e9, 1e15-1e9] +MAX = [5, 10, 20, 1e3, 1e4, 1e6, 1e9, 1e12, 1e15, 1e15] +type = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] + +params = [MIN, MAX, type] + +def solve(N): + risposta = 1; + while N > 2: + if N%2 == 1: + N += 1 + else: + N /= 2 + risposta += 1 + return risposta + +def generate(MIN, MAX, type): + args = set(locals()) | set(['args']) + + # base generator + N = random.randint(int(MIN), int(MAX)) + + # additional state for visualizer + sol = solve(N) + + return {k:v for k,v in locals().items() if k not in args} + +testcases = [] +for args in zip(*params): + testcases.append(generate(*args)) +print(json.dumps(list(testcases))) diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/visualizer.jsx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/visualizer.jsx new file mode 100644 index 0000000..63a7834 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-3-calcolatrice/visualizer.jsx @@ -0,0 +1,29 @@ +import React from "react"; +import { range } from "lodash-es"; + +import { Canvas, Sprite, Rectangle, Variables } from "~/utils/visualizer"; + +import bunny from "./asy/bunny.asy?w=100"; +import calcolatrice from "./calcolatrice.svg?w=200"; + +export default function Visualizer({ variables }) { + const { blocklyVariables, hiddenState } = variables; + if (!hiddenState) return; + + var num; + if (hiddenState.N < 10000) { + num = {hiddenState.N}} /> + } + + return ( + <> + + + + + {num} + + + + ); +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/bunny.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/bunny.asy new file mode 100644 index 0000000..f8f6fe5 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/bunny.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/bunny_polychrome.asy" as bunny; + +add(reflect((2, 1), (2, 0))*bunny.drawing(0.85, bunny.bunny_col)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/platform.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/platform.asy new file mode 100644 index 0000000..e5b2aa7 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/platform.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/platform.asy" as platform; + +add(platform.drawing(8, 1, .75, (0,0), 0, deepgray, (0.5*deepgray + 0.5*white)+5)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/pole.asy b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/pole.asy new file mode 100644 index 0000000..d088994 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/asy/pole.asy @@ -0,0 +1,5 @@ +unitsize(1cm); + +access "../../../../../asy_library/pictures/pole.asy" as pole; + +add(pole.drawing(15, 1, (0,0), 90, lightgray, (0.5*lightgray + 0.5*black)+5)); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/customBlocks.yaml b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/customBlocks.yaml new file mode 100644 index 0000000..3dbdfad --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/customBlocks.yaml @@ -0,0 +1,218 @@ +- type: start + message0: inizia qui + nextStatement: null + colour: 20 + tooltip: L'esecuzione inizia da qui + helpUrl: "" + maxInstances: 1 + js: "" + +- type: N + message0: N + output: Number + colour: 20 + tooltip: il numero di ostacoli + helpUrl: "" + js: + - hiddenState.N + - ORDER_MEMBER + +- type: pedana alta + message0: pedana alta %1 + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + output: Number + colour: 20 + tooltip: l'altezza della pedana più in alto dell'ostacolo dato + helpUrl: "" + js: + - |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "l'ostacolo " + i + " non esiste"); + return hiddenState.A[i-1]; + })(%0) + - ORDER_FUNCTION_CALL + +- type: pedana bassa + message0: pedana bassa %1 + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + output: Number + colour: 20 + tooltip: l'altezza della pedana più in basso dell'ostacolo dato + helpUrl: "" + js: + - |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "l'ostacolo " + i + " non esiste"); + return hiddenState.B[i-1]; + })(%0) + - ORDER_FUNCTION_CALL + +- type: differenza assoluta + message0: differenza assoluta tra %1 e %2 + args0: + - type: input_value + name: FIRST + value: 0 + check: Number + - type: input_value + name: SECOND + value: 0 + check: Number + output: Number + colour: 20 + tooltip: la differenza assoluta tra x e y + helpUrl: "" + js: + - |- + (function(x, y) { + if (x === undefined || y === undefined) exit(false, "un argomento del blocco non ha un valore"); + if (x < y) return y - x; + else return x - y; + })(%0, %1) + - ORDER_FUNCTION_CALL + +- type: minimo + message0: minimo tra %1 e %2 + args0: + - type: input_value + name: FIRST + value: 0 + check: Number + - type: input_value + name: SECOND + value: 0 + check: Number + output: Number + colour: 20 + tooltip: il valore minimo tra x e y + helpUrl: "" + js: + - |- + (function(x, y) { + if (x === undefined || y === undefined) exit(false, "un argomento del blocco non ha un valore"); + if (x < y) return x; + else return y; + })(%0, %1) + - ORDER_FUNCTION_CALL + +- type: termina + message0: termina in %1 tempo + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + previousStatement: null + colour: 20 + tooltip: termina in x tempo + helpUrl: "" + js: |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 0 || Math.floor(i) != i) exit(false, "tempo " + i + " non valido"); + if (i > hiddenState.sol) exit(false, "potevi metterci meno di " + i + " tempo"); + if (i < hiddenState.sol) exit(false, "non si può finire il livello in " + i + " tempo"); + exit(true, i + " è il tempo minimo per finire il livello, complimenti!"); + })(%0); + +- type: valore pedana alta + message0: valore pedana alta %1 + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + output: Number + colour: 20 + tooltip: valore salvato per la pedana più in alto dell'ostacolo dato + helpUrl: "" + js: + - |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "l'ostacolo " + i + " non esiste"); + return hiddenState.VA[i-1]; + })(%0) + - ORDER_FUNCTION_CALL + +- type: valore pedana bassa + message0: valore pedana bassa %1 + args0: + - type: input_value + name: LENGTH + value: 0 + check: Number + output: Number + colour: 20 + tooltip: valore salvato per la pedana più in basso dell'ostacolo dato + helpUrl: "" + js: + - |- + (function(i) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "l'ostacolo " + i + " non esiste"); + return hiddenState.VB[i-1]; + })(%0) + - ORDER_FUNCTION_CALL + +- type: imposta valore pedana alta + message0: imposta valore pedana alta %1 a %2 + args0: + - type: input_value + name: INDEX + value: 0 + check: Number + - type: input_value + name: VALUE + value: 0 + check: Number + previousStatement: null + nextStatement: null + colour: 20 + tooltip: salva un valore per la pedana più in alto dell'ostacolo dato + helpUrl: "" + js: |- + (function(i, x) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "l'ostacolo " + i + " non esiste"); + hiddenState.VA[i-1] = x; + })(%0, %1); + +- type: imposta valore pedana bassa + message0: imposta valore pedana bassa %1 a %2 + args0: + - type: input_value + name: INDEX + value: 0 + check: Number + - type: input_value + name: VALUE + value: 0 + check: Number + previousStatement: null + nextStatement: null + colour: 20 + tooltip: salva un valore per la pedana più in basso dell'ostacolo dato + helpUrl: "" + js: |- + (function(i, x) { + if (i === undefined) exit(false, "l'argomento del blocco non ha un valore"); + if (i < 1 || i > hiddenState.N || Math.floor(i) != i) + exit(false, "l'ostacolo " + i + " non esiste"); + hiddenState.VB[i-1] = x; + })(%0, %1); diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/initialBlocks.json b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/initialBlocks.json new file mode 100644 index 0000000..64bd836 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/initialBlocks.json @@ -0,0 +1,14 @@ +{ + "blocks": { + "languageVersion": 0, + "blocks": [ + { + "type": "start", + "id": "y=zq)Uya2A/{vyOtN[i6", + "x": 61, + "y": 81 + } + ] + }, + "variables": [] +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/question.mdx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/question.mdx new file mode 100644 index 0000000..dfe4db5 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/question.mdx @@ -0,0 +1,57 @@ +import initialBlocks from "./initialBlocks.json"; +import customBlocks from "./customBlocks.yaml"; +import testcases from "./testcases.py"; +import Visualizer from "./visualizer.jsx"; + +Il nuovissimo videogioco *SuperBunny* è finalmente in commercio! Bunny, il protagonista del videogioco, in ogni livello deve superare $N$ ostacoli numerati da $1$ ad $N$. +Su ogni ostacolo ci sono $2$ pedane (ad altezze diverse) su cui Bunny può saltare: l'ostacolo numero $i$ è fatto da una pedana più in alto che si trova ad una altezza di $A_i$ metri, e da una pedana più in basso ad un'altezza di $B_i$ metri. + +Bunny parte da terra ad altezza $0$ e deve per prima cosa saltare sull'ostacolo numero $1$ scegliendo una delle due pedane. Una volta raggiunto l'ostacolo $1$, sceglierà una delle due pedane dell'ostacolo successivo, il $2$, e ci salterà sopra. +L'obiettivo del gioco è superare in ordine tutti gli ostacoli fino all'ostacolo numero $N$. Anche se Bunny può scegliere ogni volta su quale pedana di un ostacolo saltare, non tutti i salti sono uguali! +Infatti, più il salto è grande e più tempo ci vuole per farlo. Per saltare da pedana ad altezza $h$ fino ad una pedana sull'ostacolo successivo ad altezza $k$, Bunny ci metterà una quantità di secondi pari alla _differenza assoluta_ tra $h$ e $k$. + +_**Nota:** la differenza assoluta tra $h$ e $k$, in formule $|h - k|$, indica il valore della differenza tra $h$ e $k$ ignorando il segno: quindi $h - k$ se $h > k$ o $k - h$ se $k > h$._ + +Il tempo totale impiegato per completare un livello è la somma dei tempi impiegati in ogni salto. Quanti secondi servono a Bunny per completare il livello? +Puoi usare questi blocchi: + +- `N`: il numero $N$ di ostacoli. +- `pedana alta i`: l'altezza $A_i$ della $i$-esima pedana più in alto. +- `pedana bassa i`: l'altezza $B_i$ della $i$-esima pedana più in basso. +- `differenza assoluta tra x e y`: la differenza assoluta $|x - y|$ tra $x$ e $y$. +- `minimo tra x e y`: il valore minimo tra due numeri $x$ e $y$. +- `termina in x tempo`: riporta che è possibile raggiungere l'$N$-esimo ostacolo in $x$ tempo. + +Inoltre, se ti serve, avrai la possibilità di annotarti un valore a tua scelta su ogni piattaforma, che verrà anche mostrato nella figura, con questi blocchi: + +- `valore pedana alta i`: il valore scritto sulla pedana alta $i$-esima. +- `valore pedana bassa i`: il valore scritto sulla pedana bassa $i$-esima. +- `imposta valore pedana alta i a x`: scrivi sulla pedana alta $i$-esima il valore $x$. +- `imposta valore pedana bassa i a x`: scrivi sulla pedana bassa $i$-esima il valore $x$. + +_**Attenzione:** non ti viene richiesto di ricostruire i salti da fare, basta che calcoli il tempo necessario!_ + +_**Avvertimento:** incastrare un blocco grosso in un altro blocco può non essere semplice. Cerca di mettere la **punta sinistra** del blocco grosso nello spazio in cui vuoi inserirlo, per non avere difficoltà!_ + + + +> Un possibile programma corretto è il seguente: +> +> ![soluzione](sol.png) +> +> In questo programma, segnamo come valore su ciascuna pedana il **tempo minimo per raggiungerla**. +> Per le pedane sul primo ostacolo, il tempo per raggiungerle è pari alla loro altezza. +> Per ogni pedana successiva (alta o bassa), il tempo minimo per raggiungerla è pari al minimo tra due cose: +> +> - se decidiamo di arrivarci dalla pedana alta precedente, allora è pari al tempo minimo (valore) della pedana alta precedente, più la differenza assoluta tra la pedana che stiamo considerando e la pedana alta precedente; +> - se decidiamo di arrivarci dalla pedana bassa precedente, allora si può calcolare analogamente ma considerando il valore e la differenza assoluta con la pedana bassa precedente. +> +> Una volta scritti tutti questi valori, il migliore tempo per chiudere il livello sarà il minore +> tra il tempo minimo (valore) per raggiungere l'ultima pedana alta, e il tempo minimo (valore) +> per raggiungere l'ultima pedana bassa. \ No newline at end of file diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/sol.png b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/sol.png new file mode 100644 index 0000000..dc56ad3 Binary files /dev/null and b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/sol.png differ diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/testcases.py b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/testcases.py new file mode 100644 index 0000000..7176592 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/testcases.py @@ -0,0 +1,55 @@ +from random import randint, seed +import json +import math + +seed(0) + +N = [2, 5, 10, 25, 50, 100, 200, 500, 800, 1000] +INF = [15, 30, 25, 10, 20, 100, 300, 1000, 3000, 10000] +type = [0, 0, 0, 1, 0, 1, 0, 0, 0, 0] + +params = [N, INF, type] + +def solve(N, A, B): + A = [0] + A + B = [0] + B + TA = [0, 0] + TB = [0, 0] + + for i in range(N): + TA[(i+1)%2] = min(abs(A[i+1]-A[i]) + TA[i%2], abs(A[i+1]-B[i]) + TB[i%2]) + TB[(i+1)%2] = min(abs(B[i+1]-A[i]) + TA[i%2], abs(B[i+1]-B[i]) + TB[i%2]) + + return min(TA[N%2], TB[N%2]) + +def generate(n, INF, type): + args = set(locals()) | set(['args']) + + # base generator + N = n + A = [] + B = [] + + if type == 1: + # rottura greedy + goal = randint((INF*4)//5, INF) + for i in range(N): + A.append(randint(goal-2, goal+2)) + B.append(randint(1, INF//5)) + else: + for i in range(N): + A.append(randint(1, INF)) + B.append(randint(1, A[i])) + + VA = [0 for _ in range(N)] + VB = [0 for _ in range(N)] + + # additional state for visualizer + sol = solve(N, A, B) + + return {k:v for k,v in locals().items() if k not in args} + +testcases = [] +for args in zip(*params): + testcases.append(generate(*args)) +print(json.dumps(list(testcases))) diff --git a/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/visualizer.jsx b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/visualizer.jsx new file mode 100644 index 0000000..44e8e49 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/contest/s-4-superbunny/visualizer.jsx @@ -0,0 +1,43 @@ +import React from "react"; +import { range } from "lodash-es"; + +import { Canvas, Sprite, Rectangle, Variables } from "~/utils/visualizer"; + +import bunny from "./asy/bunny.asy?w=50"; +import pole from "./asy/pole.asy?w=15"; +import platform from "./asy/platform.asy?w=90"; + +export default function Visualizer({ variables }) { + const { blocklyVariables, hiddenState } = variables; + if (!hiddenState) return; + + var xoffs = 3; + var yoffs = 6.5; + var poles = []; + var platforms = []; + var hmax = 0; + if (hiddenState.N <= 50) { + for (var i=0; i) + platforms.push() + platforms.push() + h = hiddenState.B[i]/hmax*2+0.1; + platforms.push() + platforms.push() + } + } + + return ( + <> + + + + {poles} + {platforms} + + + + ); +} diff --git a/src/fibonacci-secondarie/2023-terza-fase/index.jsx b/src/fibonacci-secondarie/2023-terza-fase/index.jsx new file mode 100644 index 0000000..f8bc958 --- /dev/null +++ b/src/fibonacci-secondarie/2023-terza-fase/index.jsx @@ -0,0 +1,16 @@ +import { OlinfoAuth } from "~/utils/olinfo-auth"; + +import Header from "./contest/header.md"; +import Statement from "./contest/contest.mdx"; + +export const title = "Giochi di Fibonacci 2023/2024 - Fase Finale"; +export const description = "Fase Finale dei Giochi di Fibonacci 2023/2024"; + +export function App() { + return ( + +
+ + + ); +} diff --git a/src/index.jsx b/src/index.jsx index 29dfbfc..2c2c741 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -20,7 +20,7 @@ const contests = { }, "fibonacci-secondarie": { name: "Giochi di Fibonacci - Scuole secondarie", - editions: ["2023 - Seconda fase", "2023 - Seconda fase - Demo", "2023 - Prima fase", "2022 - Prima fase"], + editions: ["2023 - Terza fase", "2023 - Seconda fase", "2023 - Seconda fase - Demo", "2023 - Prima fase", "2022 - Prima fase"], }, scolastiche: { name: "Selezioni scolastiche delle Olimpiadi Italiane di Informatica",