Challenges en langage Uiua (D’après les MPO du forum Silicium)

Initiation au langage Uiua


🧩 Challenge 4 : Périmètre et surface d’un rectangle

🎯 Énoncé

Soit un rectangle de côté a et b.

Avec a et b respectivement sur la pile, faire un programme qui sort le Périmètre du rectangle et la Surface du rectangle.

Les formules utilisées sont :

  • Périmètre : P = 2(a+b)
  • Surface : S = a × b

🔑 Mots-clés Uiua

⊃ – Appeler deux fonctions sur une même valeur
×₂ – Multiplier par 2

🧠 Solution Uiua

CHA₄ ← ×₂⊃+×

🔍 Explications

La fonction CHA₄ est conçue pour calculer à la fois la surface et le périmètre d’un rectangle à partir des longueurs de ses côtés, en laissant les deux résultats sur la pile.

L’opérateur  permet d’appliquer les deux calculs et de conserver la Surface et le Périmètre sur la pile dans l’ordre requis par l’énoncé.

  1. Calcul de la Surface : L’opérateur × (multiplication) calcule la surface (S=a×b).
  2. Calcul du Périmètre : L’opérateur + (addition) calcule d’abord la somme des côtés (a+b), puis le résultat est multiplié par 2 (×₂).

🧾 Exemples

Pour les entrées 3 et 4, la fonction donne les résultats suivants :

CHA₄ 3 4

Résultats :
12 # Surface
14 # Périmètre

🧩 Challenge 8 : Chaîne

🎯 Énoncé

Faire un programme qui inverse l’ordre des caractères d’une chaine et qui, en plus, transforme l’ensemble en minuscules.

Exemple : « sILiCIuM » donne « muicilis ».


🔑 Mots-clés Uiua

⇌ – Inverser la chaine, un vecteur ou les lignes d’un tableau
⌵ – Mettre en majuscules
¯ – Inverser la casse

🧠 Solution Uiua

CHA₈ ← ¯⌵⇌

🔍 Explications

Le programme inverse d’abord la chaîne (⇌), la met ensuite entièrement en majuscules (⌵), puis utilise l’opérateur d’inversion de casse (¯). L’inversion de casse (¯) permet de transformer toutes les majuscules résultantes en minuscules.

🧾 Exemples

CHA₈ "sILiCIuM"
→ "muicilis"

🧩 Challenge N°9 : Somme des chiffres d’un nombre

🎯 Énoncé

Soit un nombre entier positif sur la pile. Le programme doit calculer la somme de ses chiffres.

Exemple : 352791 doit retourner 27.


🔑 Mots-clés Uiua

⊥₁₀ – Décomposition du nombre en chiffres
/+ – Addition/Somme des éléments d’un vecteur

🧠 Solution Uiua

CHA₉ ← /+⊥₁₀

🔍 Explications

La fonction CHA₉ est conçue pour réaliser la somme des chiffres d’un nombre.

  1. Décomposition : L’opérateur ⊥₁₀ prend le nombre entier positif en entrée et réalise sa décomposition en chiffres (base 10).
  2. Sommation : L’opérateur /+ est ensuite appliqué pour effectuer la somme de tous les chiffres obtenus dans la liste (réduction par l’addition).

🧾 Exemple

Pour le nombre 352791, la fonction donne le résultat suivant :

CHA₉ 352791

Résultat : 27

🧩 Challenge 13 : Aire d’un triangle

🎯 Énoncé

Écrire un programme qui permet de calculer la surface d’un triangle quelconque.

Le calcul de l’aire S d’un triangle quelconque, en ne connaissant que les longueurs a, b et c de ses trois côtés, est permis par la formule de Héron.

La formule est vue comme √(s(s-a)(s-b)(s-c)), où s est la demi-somme des côtés.


🔑 Mots-clés Uiua

÷₂ – Diviser par 2
⊂ – Joindre 2 éléments (scalaires, vecteurs…)
/× – Produit des éléments d’un vecteur

🧠 Solution Uiua

CHA₁₃ ← √/×-⊂0⟜(÷₂/+)

🔍 Explications

La solution implémente la formule de Héron, qui est exprimée dans les sources comme \sqrt{(s-a)(s-b)(s-c)(s-0)}

La fonction se décompose comme suit :

  1. Calcul du demi-périmètre (s): La partie (÷₂/+) calcule la demi-somme (s) des longueurs des côtés a, b, et c.
  2. Préparation du vecteur pour la soustraction: L’opération ⊂0⟜ maintient le vecteur initial des côtés (a,b,c) (⟜) et lui ajoute le nombre 0 (⊂0).
  3. Soustraction et création des termes: L’opérateur – (soustraction) est ensuite appliqué pour créer les termes (a−s),(b−s),(c−s) et (0−s).
  4. Calcul final de l’aire: Enfin, l’opération √/× réalise le produit des quatre termes et applique la racine carrée au résultat.

🧾 Exemples

Pour les entrées 4_5_6 et 3_4_5, la fonction donne les résultats suivants :

∩CHA₁₃ 4_5_6 3_4_5

Résultats :
• 6 (pour un triangle de côtés 3, 4, 5)
• 9.921567416492215 (pour un triangle de côtés 4, 5, 6)

🧩 Challenge 57 : Inversion–Addition

🎯 Énoncé

À partir d’un entier, inverse ses chiffres, additionne les deux nombres, puis recommence jusqu’à obtenir un palindrome (un nombre identique à l’envers).
Affiche le palindrome obtenu.

➡️ Bonus : trouver le premier nombre (le plus petit) qui ne génère jamais de palindrome — c’est un nombre de Lychrel.

Exemple
78 → 78 + 87 = 165
165 + 561 = 726
726 + 627 = 1353
1353 + 3531 = 4884 ✅ (palindrome)


🔑 Mots-clés Uiua

⊥₁₀ – convertir un nombres en chiffres décimaux
⍜ f g – effectuer l’opération f sur un tableau, puis g puis inverse la transformation f
⊸ – garder la valeur initiale sur la pile
⍢(action|test) – boucle : répéter une action tant qu’un test est vrai

🧠 Solution Uiua

Rev   ← ⊸⍜⊥₁₀⇌
CHA₅₇ ← ⍢(+Rev|≠Rev)

🔍 Explications

⊥₁₀ : convertit un nombre en liste de chiffres
⇌ : inverse la liste
⍜ ⊥₁₀ ⇌ : transformation ⊥₁₀ puis ⇌ et enfin transformation inverse de ⊥₁₀ (Chiffres en nombre)
⊸ : conserve le nombre d’origine
⍢(+Rev|≠Rev) : additionne avec l’inverse tant qu’on n’a pas de palindrome

🧾 Exemples

≡CHA₅₇ 165_59_89
→ [4884 1111 8813200023188]

CHA₅₇ 196
→ Error: Cannot take base of ∞

🧩 Challenge N°74 : Cubes en folie

🎯 Énoncé

Trouver tous les nombres taxi (taxicab number) inférieurs à 40000 [1].

L’origine de ce défi est célèbre : En 1919, G.H. Hardy a mentionné à Srinivasa Ramanujan que le numéro de son taxi, 1729, lui semblait banal. Ramanujan répondit qu’il s’agissait au contraire du plus petit nombre exprimable comme somme de deux cubes de deux façons .

Exemple célèbre

1729 = 1³ + 12³ = 9³ + 10³

🔑 Mots-clés Uiua

ⁿ3 ou ⁿ₃ – Calculer la puissance 3 (au cube)
⇡₁ – Générer un intervalle d’entiers, de 1 à N
˙⊞+ – Opérateur qui gère la duplication et la construction de la table de toutes les additions possibles des différents couples.
⊛♭ – Opérateur qui aplatit le tableau et assigne un index unique à chaque valeur
⊸ – Garder la valeur initiale sur la pile
⊕(>2⧻) – Grouper les éléments par leurs index, puis pour chaque groupe, compter (⧻) le nombre d’occurrences et tester s’il y en a plus que 2 (>2)
▽ – Garder (filtrer) les valeurs concernées

🧠 Solution Uiua

CHA₇₄ ← ▽⊕(>2⧻)⊸⊸⊛♭˙⊞+ⁿ₃⇡₁

🔍 Explications

La fonction CHA₇₄ est conçue pour identifier les nombres qui apparaissent au moins deux fois comme somme de deux cubes, en limitant la recherche par le paramètre N (dans l’exemple, N=35 permet de trouver les nombres taxi sous 40000).

  • ⁿ₃⇡₁ N : Cette partie calcule les puissances 3 des entiers allant de 1 jusqu’à N.
  • ˙⊞+ : Elle génère un tableau de toutes les sommes possibles en additionnant les couples de cubes obtenus.
  • ⊛♭ : L’opérateur .♭ aplatit ce tableau de sommes, et l’opérateur  assigne ensuite un index unique à chaque valeur.
  • ⊕(>2⧻) : C’est le cœur de la détection : les nombres sont groupés (⊕) selon leur index.

🧩 Challenge N°116 : Le défi du Rami en chiffres

🎯 Énoncé

Dans ce mini-jeu nommé RamiSum, les seules combinaisons valables sont celles avec au moins 3 nombres identiques .

Mission :

  • En entrée : Un nombre composé de chiffres entre 1 et 9, de taille arbitraire.
  • En sortie : Le score maximum que l’on peut obtenir, ou 0 si aucun coup n’est possible.

Exemples de combinaisons valables :

  • Pour le tirage 84884284, les combinaisons valables sont 888, 8888 et 444.
  • Pour le tirage 123456, on ne peut pas jouer.

🔑 Mots-clés Uiua

⊛ – Opérateur qui assigne des index uniques aux valeurs d’un tableau.
⊕ – Grouper les éléments.
⧻ – Compter le nombre d’occurrences ou la longueur d’un groupe.
⊢ – Garder le premier élément d’un vecteur.
>₂ – Tester si la valeur est supérieure à 2.
/↥ – Récupérer le maximum des éléments.

🧠 Solution Uiua

CHA₁₁₆ ← /↥××⊸>₂⊕⊃⧻⊢⊸⊛⊥₁₀

🔍 Explications

La fonction CHA₁₁₆ calcule le score maximum en identifiant les chiffres répétés au moins trois fois, puis en multipliant leur valeur par le nombre de fois où ils peuvent.

⊸⊛⊥₁₀ 84884284
[4 8 2 4 8 8 4 8]
[0 1 2 0 1 1 0 1]		# Il y a 3 chiffres différents (4, 8, 2) indexés par 0, 1 et 2
⊕⊃⧻⊢⊸⊛⊥₁₀ 84884284

[4 8 2]
[3 4 1]	# il y a 3 fois "4", 4 fois "8" et 1 fois "2"
⊸>₂⊕⊃⧻⊢⊸⊛⊥₁₀ 84884284
[4 8 2]	# il n'y a que des 4, 8 et 2
[3 4 1]	# 3 fois le "4", 4 fois le "8", 1 fois le "2"
[1 1 0]	# On ne garde que 3 et 4 car 1 < 3

On multiplie les 3 vecteurs pour obtenir les scores (××) et on récupère le maximum (/↥).

🧩 Challenge 142 : Nombres de Diophante

🎯 Énoncé

Trouver quatre nombres entiers tels que le produit de deux quelconques de ces nombres soit un carré moins un .

Il y a une infinité de quadruplets (a, b, c, d) tels que ab+1, ac+1, ad+1, bc+1 et cd+1 soient des carrés parfaits.

En particulier, cette condition est remplie par le quadruplet paramétrique (k-1, k+1, 4k, 4k(4k²-1)) pour tout k > 1.


🔑 Mots-clés Uiua

⇡₂ – Ajouter 2 à l’intervalle de base (décalage)
⊃ – Appeler 2 fonctions sur une même valeur
⟜ – Garder la valeur initiale en haut de la pile
⊸⊸∘ – Double duplication
⊟₄ – Combiner 4 vecteurs en une matrice
× – Multiplication
⍉ – Transposée
⇌ – Inverser l’ordre des lignes

🧠 Solution Uiua

CHA₁₄₂ ← ⍉⇌⊟₄ ×-1×⟜(⊸⊸∘⊃(×4|⊃+-1))⇡₂

🔍 Explications

Le code Uiua est conçu pour générer la série de quadruplets (k−1,k+1,4k,4k(4k² −1)).
• ⇡₂ N : Cette fonction prend N en entrée et génère un intervalle auquel elle ajoute 2, produisant la liste [2,3,4,…,N+1].
• ⊃(×4|⊃+-1) : Cet opérateur structuré est utilisé pour appliquer deux actions distinctes : la multiplication par 4 (×4), et les opérations d’ajout et soustraction de 1 (⊃+-1).
• ⟜(⊸⊸∘⊃(×4|⊃+-1))⇡₂ : On duplique deux fois l’opération de multiplication par 4. L’opérateur ⟜ maintient l’intervalle généré par ⇡₂ en haut de la pile.
• ⊟₄ : Combine les quatre vecteurs situés en haut de la pile pour former une matrice.
• ⍉⇌ : Inverse l’ordre des lignes (⇌) puis transpose (⍉) la matrice pour obtenir le format de sortie désiré.

🧾 Exemples

Pour N=20, la fonction génère les 20 premiers quadruplets.

CHA₁₄₂ 20

╭─
╷ 1 3 8 120
2 4 12 420
3 5 16 1008
4 6 20 1980
5 7 24 3432
6 8 28 5460
7 9 32 8160
8 10 36 11628
9 11 40 15960
10 12 44 21252
11 13 48 27600
12 14 52 35100
13 15 56 43848
14 16 60 53940
15 17 64 65472
16 18 68 78540
17 19 72 93240
18 20 76 109668
19 21 80 127920
20 22 84 148092
╯

Vérification

Pour le quadruplet (3,5,16,1008), on peut vérifier que les produits plus un sont bien des carrés parfaits :
• 3×5+1=16=4²
• 3×16+1=49=7²
• 3×1008+1=3025=55²
• 5×16+1=81=9²
• 16×1008+1=16129=127²

Quelques programmes pour les CASIO fx-180P

Présentation générale

Quelques modèles de ma collection

fx-180P, 180Pv, 180PA et 180P Plus

Autre version du programme Syracuse

Pas	Touches
01	2
02	Kin ÷ 1		# n / 2
03	Kout 1
04	-
05	1
06	Kin + 3 	# TOF = TOF + 1
07	=
08	1/x		# Si n = 1 arrêt sur une erreur
09	Kout 1
10	-
11	RND		# Partie entière quand on est en FIX 0
12	+
13	.
14	5
15	=		# Si n est pair on obtient 1 et 0 sinon
16	x > 0		# Retour pas n°1 si n pair
17	6		# Sinon...
18	Kin × 1
19	1
20	Kin + 1		# 3n+1
21	Kout 1
22	x ≤ M		# Si n <= max retour au pas n°1
23	Min		# sinon mise à jour du max
24	x > 0		

Exemple d’utilisation pour N = 27 puis N = 17 :

MODE FIX 0
KAC
27 Min Kin 1 P1

Le programme s'arrête sur -E-
AC puis MR pour voir le maximum (9232) et Kout 3 pour le temps de vol (111)

Pour un autre calcul faire : 
KAC
17 Min Kin 1 P1
Résultats : max = 52 et TOF = 12

Décomposition d’un entier en facteurs premiers

Programme P1 :

001	Min
002	1
003	Kin 1
004	Mode 7 0    # Fix 0

Programme P2 :

001	MR
002	÷
003	1
004	Kin + 1
005	Kout 1
006	-
007	RND
008	=
009	x > 0
010	+/-
011	x > 0       # Cela revient à tester x ≠ 0
012	Kout 1
013	HLT
014	1/x
015	×
016	MR
017	=
018	Min
019	1
020	Kin - 1
021	Kout 1
022	x ≤ M
023	AC

Utilisation : Décomposition de 2024 en facteurs premiers

2024 P1
P2
Affichage : 2
RUN
Affichage : 2
RUN
Affichage : 2
RUN
Affichage : 11
RUN
Affichage : 23
RUN
0

Donc 2024 = 2 × 2 × 2 × 11 × 23

Lorsque le nombre est premier :

13 P1
P2
Affichage : 13
RUN
0

Représentation du temps – Informatique et temps chronologique

Conflit de ressources

import threading
import time

# Nombre de tickets disponibles (ressource partagée)
nb_tickets  = 10

def achat_ticket():
  global nb_tickets 
  if nb_tickets  > 0:
    # Simuler une lecture de la base de données
    current_tickets = nb_tickets 
    # Simuler un délai
    time.sleep(0.1)
    # Simuler une écriture dans la base de données
    nb_tickets  = current_tickets - 1
    print(f"Ticket acheté, tickets restants : {nb_tickets }\n")
  else: print("Plus de tickets disponibles.\n")

# Plusieurs utilisateurs essayant d'acheter des tickets en même temps

for _ in range(20):
  threading.Thread(target=achat_ticket).start()

Version avec verrou

import threading
import time

# Nombre de tickets disponibles (ressource partagée)
nb_tickets  = 10
lock = threading.Lock()

def achat_ticket():
  global nb_tickets
  with lock:
   if nb_tickets  > 0:
    # Simuler une lecture de la base de données
    current_tickets = nb_tickets 
    # Simuler un délai
    time.sleep(0.1)
    # Simuler une écriture dans la base de données
    nb_tickets  = current_tickets - 1
    print(f"Ticket acheté, tickets restants : {nb_tickets }\n")
   else: print("Plus de tickets disponibles.\n")

# Plusieurs utilisateurs essayant d'acheter des tickets en même temps

for _ in range(20):
  threading.Thread(target=achat_ticket).start()

Version SQL

import sqlite3

def buy_ticket(event_name):
    try:
        # Connexion à la base de données SQLite (ou création de la base si elle n'existe pas)
        conn = sqlite3.connect('example.db')
        cursor = conn.cursor()

        # Démarrer une transaction
        cursor.execute('BEGIN TRANSACTION')

        # Étape 1 : Vérifier le nombre de tickets disponibles
        cursor.execute('SELECT available_tickets FROM tickets WHERE event_name = ?', (event_name,))
        result = cursor.fetchone()

        if result is None:
            print(f"Événement '{event_name}' introuvable.")
            conn.rollback()
            return

        available_tickets = result[0]
        print(f"Tickets disponibles avant l'achat : {available_tickets}")

        if available_tickets > 0:
            # Étape 2 : Réserver un ticket
            cursor.execute('UPDATE tickets SET available_tickets = available_tickets - 1 WHERE event_name = ?', (event_name,))
            print("Achat réussi !")

            # Valider la transaction
            conn.commit()
        else:
            print("Échec de l'achat : plus de tickets disponibles.")
            conn.rollback()

    except sqlite3.Error as e:
        print(f"Erreur SQL : {e}")
        conn.rollback()
    finally:
        conn.close()

# Exemple d'utilisation avec plusieurs "acheteurs"
if __name__ == "__main__":
    # Création de la table et insertion initiale (exécuté une seule fois)
    conn = sqlite3.connect('example.db')
    cursor = conn.cursor()
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS tickets (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        event_name TEXT NOT NULL,
        available_tickets INTEGER NOT NULL
    )
    ''')
    cursor.execute('INSERT INTO tickets (event_name, available_tickets) VALUES (?, ?)', ('concert', 100))
    conn.commit()
    conn.close()

    # Simulation d'achats concurrents
    for _ in range(55): buy_ticket('concert')

Fuseaux horaires

from datetime import datetime
import pytz

# Obtenir l'heure actuelle en UTC
utc_now = datetime.now(pytz.utc)
print(f"Heure actuelle en UTC : {utc_now}")

for endroit in 'Europe/Paris', 'America/New_York', 'Africa/Cairo', 'Australia/Sydney', 'Asia/Tokyo', 'Antarctica/Troll':
 local_tz = pytz.timezone(endroit)
 local_time = utc_now.astimezone(local_tz)
 print(f"Heure locale {endroit} : {local_time}")

Représentation du temps : Calendriers

Phases de la lune

cycle_lunaire = 29.53058853
delta = cycle_lunaire / 8
phases = "Nouvelle lune","Premier croissant","Premier quartier", "Gibbeuse croissante","Pleine lune","Gibbeuse décroissante","Dernier quartier","Dernier croissant"
visuel = ['🌑','🌒','🌓','🌔','🌕','🌖','🌗','🌘']

def phase_lune(nb_jours):
 nb_cycles = int(nb_jours / cycle_lunaire)
 reste = nb_jours - nb_cycles * cycle_lunaire
 tranche = int(round(reste / delta, 0) % 8)
 return phases[tranche], visuel[tranche]

>>> phase_lune(365)
('Gibbeuse croissante', '🌔')

Calendrier chinois – signes du zodiaque

def zodiaque_chinois(annee):
 elements = "Bois", "Feu", "Terre", "Métal", "Eau"
 aspects = "Yang", "Yin"
 signes_zodiaque = (
        "Rat", "Buffle", "Tigre", "Lapin", "Dragon", "Serpent",
        "Cheval", "Chèvre", "Singe", "Coq", "Chien", "Cochon"
    )
 annee_ref = 1924 # Année du Rat, début d'un cycle de 60 ans
 diff_annees = annee - annee_ref
 ind_signe_zodiaque = diff_annees % 12
 ind_aspect = diff_annees % 2
 ind_element = (diff_annees % 10) // 2
 signe_zodiaque = signes_zodiaque[ind_signe_zodiaque]
 aspect = aspects[ind_aspect]
 element = elements[ind_element]
 annee_chinoise = annee_ref + (diff_annees % 60)
 return f"{annee_chinoise} : {signe_zodiaque} ({element} {aspect})"
 
>>> zodiaque_chinois(2024)
1964 : Dragon (Bois Yang)

Comparaison JULIEn | GREGORIEN | Personnel

def bissextile_julien(annee):
 return annee % 4 == 0
 
def bissextile_gregorien(annee):
 return (annee % 4 == 0 and annee % 100 != 0) or (annee % 400 == 0)
 
def bissextile_perso(annee):
 return annee % 4 == 0 and annee % 128 != 0
 
def compare(ans, methode):
 total = 0
 for an in range(ans):
  total += 365
  if methode(an): total += 1
 return total - 365.2421904482 * ans

>>> compare(10000, bissextile_julien)
78.09551799995825

>>> compare(10000, bissextile_gregorien)
3.095517999958247

>>> compare(10000, bissextile_perso)
-0.904482000041753