vendredi 13 février 2026

WinForms

 WinForms (Windows Forms) 👇


🖥️ WinForms (Windows Forms)

1️⃣ C’est quoi WinForms ?

WinForms (Windows Forms) est une technologie de Microsoft pour créer des applications Windows desktop avec interface graphique (GUI).

  • Introduit avec .NET Framework 1.0 (2002)

  • Basé sur la bibliothèque native Win32

  • Utilisé principalement avec C# ou VB.NET

  • Toujours supporté dans les versions modernes de .NET


2️⃣ À quoi sert WinForms ?

WinForms permet de créer des applications Windows comme :

  • Applications de gestion (ERP interne, facturation…)

  • Outils métiers en entreprise

  • Applications bancaires desktop

  • Interfaces pour systèmes industriels

  • Logiciels internes rapides à développer


3️⃣ Comment ça fonctionne ?

WinForms fonctionne avec :

  • Form → la fenêtre principale

  • Contrôles → Button, TextBox, Label, DataGridView, etc.

  • Événements → Click, Load, TextChanged…

Exemple simple :

using System; using System.Windows.Forms; public class MainForm : Form { public MainForm() { Button btn = new Button(); btn.Text = "Click Me"; btn.Click += (s, e) => MessageBox.Show("Hello WinForms!"); Controls.Add(btn); } [STAThread] public static void Main() { Application.Run(new MainForm()); } }

4️⃣ Architecture WinForms

  • Programmation événementielle

  • Basé sur :

    • Form

    • Control

    • EventHandler

  • Compatible avec :

    • ADO.NET

    • Entity Framework

    • Web API

    • Services Windows


5️⃣ Avantages

✅ Facile à apprendre
✅ Rapide à développer
✅ Designer visuel dans Visual Studio
✅ Très stable en entreprise
✅ Parfait pour applications internes


6️⃣ Inconvénients

❌ UI moins moderne que WPF ou MAUI
❌ Moins flexible pour design avancé
❌ Windows uniquement


7️⃣ WinForms vs autres technologies

TechnologieTypeModerneCross-platform
WinFormsDesktop Windows⭐⭐
WPFDesktop Windows⭐⭐⭐⭐
MAUIDesktop + Mobile⭐⭐⭐⭐⭐
BlazorWeb⭐⭐⭐⭐⭐

8️⃣ Quand utiliser WinForms ?

👉 Application interne entreprise
👉 Projet legacy .NET Framework
👉 Outil métier rapide
👉 Maintenance application existante


💡 En résumé :

WinForms est une technologie simple, stable et robuste pour créer des applications Windows desktop.
Elle est encore très utilisée en entreprise, surtout dans les environnements bancaires et industriels.

Task vs ValueTask

 

Task et ValueTask sont deux façons de représenter une opération asynchrone qui peut se compléter dans le futur, mais elles ont des différences importantes de performance et d’usage. Voyons ça en détail.


1. Task

  • Type référence (class) qui représente une opération asynchrone.

  • Toujours alloué sur le heap.

  • Peut être awaité avec await.

  • Facile à utiliser et très courant.

  • Supporte la composition, comme Task.WhenAll et Task.WhenAny.

Exemple :

async Task<int> GetNumberAsync() { await Task.Delay(1000); return 42; } int result = await GetNumberAsync(); Console.WriteLine(result); // 42

Points clés :

  • Allocation sur le heap → un peu plus lourd si beaucoup de petites tâches rapides.

  • Toujours sûr pour les opérations qui doivent être awaitées plusieurs fois.


2. ValueTask

  • Type struct (valeur type) → peut éviter des allocations sur le heap pour des tâches très rapides ou souvent synchrones.

  • Peut être awaité comme un Task.

  • Recommandé quand la tâche peut se terminer immédiatement ou retourner un résultat déjà disponible.

  • Attention : si vous attendez plusieurs fois le même ValueTask, vous devez le convertir en Task (AsTask()), sinon comportement indéfini.

Exemple :

async ValueTask<int> GetNumberFastAsync(bool cached) { if (cached) return 42; // pas de Task allouée await Task.Delay(1000); return 43; } int result = await GetNumberFastAsync(true); Console.WriteLine(result); // 42

Points clés :

  • Réduit les allocations heap pour les opérations rapides.

  • Moins flexible que Task si vous devez réutiliser ou combiner la tâche.

  • Ne pas utiliser pour des tâches longues ou partagées à plusieurs endroits.


3. Comparaison rapide

CaractéristiqueTaskValueTask
TypeReference type (class)Value type (struct)
Allocation heapOuiNon si résultat immédiat
RéutilisableOuiNon, il ne doit pas être awaité plusieurs fois
Usage recommandéToutes opérations asynchronesOpérations très rapides ou souvent synchrones
Composition (WhenAll, etc.)FacileMoins pratique, doit convertir en Task

Règle pratique

  • Task → sûr, simple, standard pour la plupart des cas.

  • ValueTask → optimisation pour micro-performances, surtout si beaucoup de tâches se terminent immédiatement.

record

 C’est un concept introduit dans C# 9 et amélioré dans les versions suivantes. C’est devenu très populaire pour les objets immuables et les modèles de données.


1. Qu’est-ce qu’un record ?

  • Un record est un type référence (comme une class) par défaut, mais avec des comportements spéciaux :

    • Comparaison par valeur au lieu de par référence

    • Syntaxe simplifiée pour définir des propriétés immuables

    • Supporte le mot-clé with pour créer des copies modifiées

En gros : un record est idéal pour représenter des données plutôt que des objets avec beaucoup de comportement métier.


2. Syntaxe de base

public record Person(string FirstName, string LastName);
  • Ceci crée automatiquement :

    • Propriétés publiques FirstName et LastName

    • Constructeur

    • Méthodes Equals() et GetHashCode() basées sur les valeurs

    • ToString() lisible : "Person { FirstName = John, LastName = Doe }"

Exemple d’utilisation :

var p1 = new Person("John", "Doe"); var p2 = new Person("John", "Doe"); Console.WriteLine(p1 == p2); // True, comparaison par valeur

3. Copier avec with

  • Vous pouvez créer une nouvelle instance basée sur une existante avec certaines modifications :

var p3 = p1 with { LastName = "Smith" }; Console.WriteLine(p3); // Person { FirstName = John, LastName = Smith }

4. Variantes importantes

a) record class (référence)

  • Le type par défaut, comparable par valeur

  • Exemple :

public record class PersonClass(string Name, int Age);

b) record struct (C# 10+)

  • Valeur type, comparable par valeur

  • Idéal pour petites données immuables

public readonly record struct Point(int X, int Y);

c) positional record

  • Déjà montré : propriétés et constructeur en une seule ligne

public record Person(string FirstName, string LastName);

d) record with mutable properties

  • Vous pouvez avoir des propriétés modifiables, mais la comparaison reste par valeur

public record Person { public string Name { get; set; } public int Age { get; set; } }

5. Avantages du record

  1. Comparaison par valeur (utile pour tests et collections)

  2. Syntaxe concise pour déclarer des objets de données

  3. Immutabilité facile avec init :

public record Person { public string Name { get; init; } // Peut être défini uniquement à l'initialisation }
  1. Supporte with pour copier et modifier des objets sans changer l’original


En résumé :

TypeComparaisonImmuable par défautExemple syntaxe
record classpar valeurOuirecord Person(string Name, int Age);
record structpar valeurOuirecord struct Point(int X, int Y);


========================

comparaison claire et complète entre struct, class et record en C#, surtout dans les versions récentes de C# (9/10+) :


1. Différences principales

Caractéristiquestructclassrecord
TypeValeur (value type)Référence (reference type)Référence par défaut (record class) ou valeur (record struct)
StockageStack (ou inline dans un objet)HeapHeap (record class) / Stack (record struct)
CopieCopie les donnéesCopie la référenceCopie par valeur (record struct) ou par référence (record class)
ComparaisonPar champs si override EqualsPar référence par défautPar valeur (tous les champs sont comparés)
MutabilitéMutable par défaut, peut être readonlyMutable par défaut, mais peut être immutableImmutable par défaut (record class/struct), modifiable avec init
HéritageNe peut pas hériter d’une struct/classSupporte héritageSupporte héritage (record class)
with support✅ (crée une copie avec modification)
Usage idéalPetits objets, performances, structs légersObjets complexes avec logique et héritageObjets de données immuables, modèles DTO, configuration

2. Exemples pratiques

a) Struct

struct Point { public int X, Y; } Point p1 = new Point { X = 1, Y = 2 }; Point p2 = p1; // Copie p2.X = 10; Console.WriteLine(p1.X); // 1

b) Class

class Person { public string Name; } Person person1 = new Person { Name = "Alice" }; Person person2 = person1; // Même référence person2.Name = "Bob"; Console.WriteLine(person1.Name); // Bob

c) Record (C# 9+)

record PersonRecord(string Name, int Age); var r1 = new PersonRecord("Alice", 30); var r2 = r1 with { Age = 31 }; // Copie avec modification Console.WriteLine(r1); // PersonRecord { Name = Alice, Age = 30 } Console.WriteLine(r2); // PersonRecord { Name = Alice, Age = 31 } Console.WriteLine(r1 == r2); // False, comparaison par valeur

3. Résumé rapide

ConceptQuand l’utiliser ?
structPetits objets simples, copies fréquentes, performances critiques
classObjets complexes, héritage, logique métier
recordObjets de données immuables, comparaison par valeur, DTOs, API responses

💡 Astuce :

  • Si tu manipules des données immuablesrecord

  • Si tu as un objet lourd avec héritageclass

  • Si tu as une petite structure légèrestruct

Dynamic Programming (DP)

 Dynamic Programming (DP), c’est un concept clé en algorithmique, souvent utilisé pour résoudre des problèmes complexes qui peuvent être découpés en sous-problèmes plus simples.


1. Idée principale

Dynamic Programming consiste à éviter de recalculer plusieurs fois les mêmes sous-problèmes.
Autrement dit, si ton problème peut être divisé en plusieurs sous-problèmes qui se répètent, DP permet de mémoriser leurs résultats pour les réutiliser.

C’est un peu comme faire ses devoirs une seule fois et garder les réponses pour ne pas les refaire.


2. Quand utiliser DP ?

Il y a deux conditions importantes :

  1. Optimal Substructure (sous-structure optimale) :
    La solution globale peut être construite à partir des solutions optimales de ses sous-problèmes.
    Exemple : pour trouver le plus court chemin dans un graphe, le chemin optimal de A à C passe par le chemin optimal de A à B et de B à C.

  2. Overlapping Subproblems (sous-problèmes qui se répètent) :
    Les mêmes sous-problèmes apparaissent plusieurs fois dans la résolution du problème.
    Exemple : Fibonacci : pour calculer F(5), on calcule F(3) et F(4), mais F(3) est recalculé si on n’utilise pas DP.


3. Deux manières de faire DP

  1. Top-down avec mémorisation (Memoization)

    • On résout le problème de façon récursive, mais on stocke les résultats déjà calculés.

    • Exemple : Fibonacci avec mémorisation.

  2. Bottom-up avec tabulation

    • On commence par résoudre les plus petits sous-problèmes, puis on construit progressivement la solution finale.

    • Exemple : Fibonacci avec un tableau dp[n].


4. Exemple simple : Fibonacci

Sans DP (beaucoup de calculs redondants)

F(5) = F(4) + F(3) F(4) = F(3) + F(2)

Ici F(3) est calculé deux fois !

Avec DP (mémorisation)

dp[0] = 0 dp[1] = 1 dp[2] = dp[1] + dp[0] = 1 dp[3] = dp[2] + dp[1] = 2 dp[4] = dp[3] + dp[2] = 3 dp[5] = dp[4] + dp[3] = 5

Maintenant, chaque valeur est calculée une seule fois.


En résumé :

Dynamic Programming = découper + mémoriser + reconstruire la solution optimale.

Introduction to Clean Code

 

Clean Code refers to writing software in a way that is easy to read, maintain, and extend. It is not just about making the program work—it’s about making the code understandable for humans.

Robert C. Martin (“Uncle Bob”), who popularized the concept, emphasizes that clean code is readable, simple, and expressive.


Why Clean Code Matters

  • Readability: Other developers (or even yourself in the future) can understand it quickly.

  • Maintainability: Easier to fix bugs or add features.

  • Reduced complexity: Fewer errors and better software design.

  • Team productivity: Clean code reduces misunderstandings and technical debt.


Key Principles of Clean Code

  1. Meaningful Names

    • Variables, functions, and classes should clearly express their purpose.

    • Example: Use calculateInvoiceTotal() instead of doCalc().

  2. Small Functions

    • Each function should do one thing and do it well.

    • Example: Instead of a 50-line processOrder() function, split it into validateOrder(), calculateTotal(), saveOrder().

  3. Readable Code

    • Code should read like a story.

    • Avoid clever hacks that confuse readers.

  4. Consistent Formatting

    • Follow naming conventions, indentation, and spacing consistently.

    • Makes the code predictable and easier to scan.

  5. Avoid Duplicated Code

    • Use reusable functions or modules.

    • Duplication increases maintenance cost and risk of bugs.

  6. Handle Errors Properly

    • Don’t ignore exceptions; handle them clearly and consistently.

    • Avoid error codes scattered in the logic.

  7. Write Tests

    • Unit tests ensure your code works and supports refactoring safely.


Example: Clean vs Dirty Code

Dirty Code:

double a = 0; for (int i = 0; i < items.Count; i++) { a += items[i].p * items[i].q; } Console.WriteLine(a);

Clean Code:

double totalPrice = CalculateTotalPrice(items); Console.WriteLine(totalPrice); double CalculateTotalPrice(List<Item> items) { double total = 0; foreach (var item in items) { total += item.Price * item.Quantity; } return total; }
  • Notice how naming and structure make the clean version easier to read and understand.


Summary

  • Clean code is about clarity, simplicity, and maintainability.

  • Writing clean code is an investment that pays off in the long term, especially in team projects or complex systems.

  • Combine clean code practices with TDD and SOLID principles for high-quality software.

Introduction to SOLID Principles

 

SOLID is an acronym that represents five key principles of object-oriented software design. Following these principles helps developers create robust, maintainable, and scalable systems.

1. S – Single Responsibility Principle (SRP)

A class should have only one reason to change.

  • Each class should do one thing and do it well.

  • Changes in requirements should affect only one class, reducing risk of bugs.

Example:

  • A ReportGenerator class should generate reports, but not handle saving them to disk. Saving can be a separate ReportSaver class.


2. O – Open/Closed Principle (OCP)

Software entities should be open for extension, but closed for modification.

  • You should be able to add new functionality without changing existing code.

  • Achieved via inheritance or interfaces.

Example:

  • A PaymentProcessor interface allows adding new payment methods (Credit Card, PayPal) without modifying existing processors.


3. L – Liskov Substitution Principle (LSP)

Subtypes must be replaceable for their base types without affecting correctness.

  • Derived classes should behave consistently with their base class.

  • Prevents unexpected behavior when substituting subclasses.

Example:

  • If Bird has a Fly() method, a subclass Penguin should not inherit it if penguins cannot fly. Better to redesign the hierarchy.


4. I – Interface Segregation Principle (ISP)

Clients should not be forced to depend on interfaces they do not use.

  • Split large interfaces into smaller, specific ones.

  • Makes code easier to implement and maintain.

Example:

  • Instead of a Machine interface with Print(), Scan(), and Fax(), create separate IPrinter, IScanner, IFax interfaces.


5. D – Dependency Inversion Principle (DIP)

High-level modules should not depend on low-level modules. Both should depend on abstractions.

  • Reduces coupling and increases flexibility.

  • Use interfaces or abstract classes to decouple dependencies.

Example:

  • A ReportService depends on an ILogger interface rather than a concrete FileLogger. You can switch to DatabaseLogger without changing ReportService.


Summary

  • SOLID principles help make code clean, flexible, and maintainable.

  • Applying them reduces bugs, simplifies testing, and allows safe changes.

Test-Driven Development

 

Introduction to TDD (Test-Driven Development)

Test-Driven Development (TDD) is a software development methodology in which tests are written before writing the actual code. It follows a short, iterative cycle that ensures code correctness and maintainability.

Core Idea

  • Instead of writing the program first and testing later, TDD flips the process: write a test → write code → refactor.

  • It helps developers focus on requirements, reduces bugs, and encourages simple, clean design.

TDD Cycle (Red-Green-Refactor)

  1. Red: Write a test for the next piece of functionality. Since the feature isn’t implemented yet, the test fails.

  2. Green: Write the minimal code required to pass the test.

  3. Refactor: Clean up the code while keeping the test passing. Remove duplication and improve design.

Benefits of TDD

  • Higher code quality: Each feature is covered by automated tests.

  • Early bug detection: Issues are found immediately when code is written.

  • Better design: Encourages modular, loosely coupled code.

  • Documentation: Tests serve as live documentation for how the system should behave.

Example (Simplified in C#)

// Test first [Test] public void Add_TwoNumbers_ReturnsSum() { var result = Calculator.Add(2, 3); Assert.AreEqual(5, result); } // Minimal implementation to pass the test public static class Calculator { public static int Add(int a, int b) => a + b; }

Best Practices

  • Keep tests small and focused.

  • Test only one behavior per test.

  • Run tests frequently to catch errors early.

  • Refactor code without breaking tests.

jeudi 12 février 2026

rendu de monnaie [1, 2, 5]

 Rédiger l'algorithme glouton pour le problème du rendu de monnaie. On testera notre programme avec le système de monnaie suivant : euros = [1, 2, 5].



===

un algorithme glouton classique pour le problème du rendu de monnaie et l’adapter au système d’euros [1, 2, 5]. Je vais aussi expliquer la logique étape par étape.


1️⃣ Problème

Entrée :

  • Un montant N à rendre.

  • Un ensemble de pièces disponibles euros = [1, 2, 5].

Sortie :

  • Le nombre minimal de pièces utilisées pour rendre N.

  • La liste des pièces choisies.

Idée du glouton :

  • À chaque étape, choisir la plus grande pièce possible ≤ montant restant.

  • Répéter jusqu’à ce que le montant restant soit 0.

Le glouton fonctionne correctement ici car les pièces sont “canonique” : [1, 2, 5]


2️⃣ Algorithme en pseudo-code

Entrée : montant N, tableau euros trié décroissant Sortie : liste de pièces utilisées, nombre total de pièces Algorithme RenduGlouton(N, euros): Trier euros en ordre décroissant liste_pieces [] reste N pour chaque piece dans euros: tant que reste >= piece: liste_pieces.ajouter(piece) reste reste - piece retourner liste_pieces, longueur(liste_pieces)

3️⃣ Exemple avec N = 11

euros = [5, 2, 1] N = 11 - prendre 5 → reste = 6, liste = [5] - prendre 5 → reste = 1, liste = [5,5] - prendre 2 → reste = 1 < 2 → ignorer - prendre 1 → reste = 0, liste = [5,5,1] Résultat : pièces = [5,5,1], nombre = 3

4️⃣ Implémentation C#

using System; using System.Collections.Generic; class RenduMonnaie { static void Main() { int[] euros = { 1, 2, 5 }; int montant = 11; List<int> pieces = RenduGlouton(montant, euros); Console.WriteLine("Pièces utilisées : " + string.Join(", ", pieces)); Console.WriteLine("Nombre total de pièces : " + pieces.Count); } static List<int> RenduGlouton(int N, int[] euros) { // Trier décroissant Array.Sort(euros); Array.Reverse(euros); List<int> listePieces = new List<int>(); int reste = N; foreach (int piece in euros) { while (reste >= piece) { listePieces.Add(piece); reste -= piece; } } return listePieces; } }

5️⃣ Exemple de sortie

Montant = 11 Pièces utilisées : 5, 5, 1 Nombre total de pièces : 3

✅ Correct et optimal pour ce système [1, 2, 5].

prix = [100,98,105,102,110,107,115,112,120,117].

 un trader effectue des operations d'achat et vendre d'une seule action sur une periode de 10 jours . Chque jour, le prix de action est donnee dans un tableaux. Contraintes: le trader ne peut effectuer qu'une seule operation par jour: soit acheter une action, soit en vendre une. Il ne peut pas achter et vendre le meme jour, le trader ne peut detenir qu'une seule action a la fois, le trader peut commencer par vendre une action (ce qui signifie qu'il commence par une position courte), chaque fois qu'il change de position (c'est a dire qu'apres avoir achete il vend, ou apres avoir vendu il achete) il doit payer une commission fixe de 2 unites monetaires, l'objectif est de maximiser le gain total net (c'est a dire la somme des profits et pertes realises sur les operations, apres deduction des commissions. Donnees: un tableau prix de taille 10 contenant les prix de l'action pour chauqe jour: prix = [100,98,105,102,110,107,115,112,120,117]. Objectif: en c#, ecrire un algorithme qui, a partir du tableau des prix, determiner la strategie d'achat/vente (une seule operation par jour) permettant de maximiser le gain total net sur 10 jours)


===============


Ý tưởng (rất gọn)

Mỗi ngày chỉ cần giữ 3 giá trị tốt nhất:

  • flat: đang không giữ vị thế (lời/lỗ đã “chốt” hết)

  • longPos: đang giữ LONG (đã mua 1 cổ)

  • shortPos: đang giữ SHORT (đã bán khống 1 cổ)

Mỗi ngày ta có thể:

  • mở long từ flat: flat - price

  • đóng long về flat: longPos + price - fee

  • mở short từ flat: flat + price

  • đóng short về flat: shortPos - price - fee

Phí fee=2 được trừ khi đóng vị thế (tức là khi đổi trạng thái từ long/short về flat).
Kết quả cần “lợi nhuận thực hiện” ⇒ lấy flat ở ngày cuối.


=======================

using System;


class Program

{

    static void Main()

    {

        int[] prices = { 100, 98, 105, 102, 110, 107, 115, 112, 120, 117 };

        int fee = 2;


        int flat = 0;

        int longPos = -prices[0];   // mua ngày 1

        int shortPos = prices[0];   // bán khống ngày 1


        for (int i = 1; i < prices.Length; i++)

        {

            int p = prices[i];


            int newFlat = flat;

            newFlat = Math.Max(newFlat, longPos + p - fee);   // đóng long

            newFlat = Math.Max(newFlat, shortPos - p - fee);  // đóng short


            int newLong = Math.Max(longPos, flat - p);        // mở long

            int newShort = Math.Max(shortPos, flat + p);      // mở short


            flat = newFlat;

            longPos = newLong;

            shortPos = newShort;

        }


        Console.WriteLine(flat); // max profit net, kết thúc flat

    }

}


Algo

 Dancer.GetPositionAt(int n) 


Chuỗi chỉ có các ký tự : ( ) [ ]


prix = [100,98,105,102,110,107,115,112,120,117]. 


rendu de monnaie  [1, 2, 5]      algo brute force

Dancer.GetPositionAt(int n)

 Let's learna new dance! the first thing you need to know is that you can only move forward or backward. When moving backward, your number of steps will be negative. This dance require every performer to follow a precise sequence of steps: stage 0: first, get away from obstacles by setting up your starting point at position 0; stage 1: take one step forward (+1 step); stage 2: take two steps backward (-2 steps) to follow, the steps as well as the direction you will have to take in your next move will each time be obtained thanks to a specific calculation: the number of steps you took on the previous stage minus the number of steps you took on the penultimate stage (the second - last stage). That is on stage 3, a dancer will have to take 3 steps backward (-2-1). Implementer en c# the methode int Dancer.GetPositionAt(int n) to return the dancer's position at stage n. input: 0<= n <= 2147483647. important note: try to saave memory space and cpu cycles if possible. Exemples: n = 3 return -4; n = 100000 return -5 ; n = 2147483647 return 1.



This is a linear recurrence problem:

  • Stage 0 → 0 (starting position)

  • Stage 1 → +1

  • Stage 2 → -2

  • Stage n ≥ 3 → step_n = step_(n-1) − step_(n-2)

The dancer’s position at stage n is the sum of all previous steps.


Step 1: Understanding the sequence

Let’s compute the first few steps:

nstep_nposition
000
1+10 + 1 = 1
2-21 + (-2) = -1
3-2 - 1 = -3-1 + (-3) = -4
4-3 - (-2) = -1-4 + (-1) = -5
5-1 - (-3) = 2-5 + 2 = -3
62 - (-1) = 3-3 + 3 = 0
73 - 2 = 10 + 1 = 1
81 - 3 = -21 + (-2) = -1
9-2 - 1 = -3-1 + (-3) = -4
10-3 - (-2) = -1-4 + (-1) = -5

Observation:

  • The positions repeat in a cycle of 6 stages:

position sequence = 0, 1, -1, -4, -5, -3, 0, 1, -1, -4, -5, -3, ...
  • So instead of computing all steps up to huge n, we can use mod 6.


Step 2: Map n mod 6 → position

Looking at the first 6 positions:

n % 6position
00
11
2-1
3-4
4-5
5-3

✅ Perfect! This gives O(1) solution for very large n.


Step 3: C# Implementation

public static class Dancer { public static int GetPositionAt(int n) { switch (n % 6) { case 0: return 0; case 1: return 1; case 2: return -1; case 3: return -4; case 4: return -5; case 5: return -3; default: return 0; // never happens } } }

✅ Step 4: Test cases

Console.WriteLine(Dancer.GetPositionAt(3)); // -4 Console.WriteLine(Dancer.GetPositionAt(100000)); // -5 Console.WriteLine(Dancer.GetPositionAt(2147483647));// 1

  • Works for huge n (up to 2,147,483,647)

  • Uses constant memory

  • O(1) CPU → very efficient







==============================================

private int GetStep(int n)
        {
            if (n == 0) return 0;
            if (n == 1) return 1;
             if (n == 2) return -2;
            int prev2 = 1;
            int prev1 = -2;
            int step = 0;
            for (int i = 3; i <= n; i++)
            {
                step = prev1 - prev2;
                prev2 = prev1;
                prev1 = step;
            }
            return step;
        }

        // Hàm tính position_n
        private int GetPosition(int n)
        {
            int pos = 0;
            for (int i = 0; i <= n; i++)
            {
                pos += GetStep(i);
            }
            return pos;
        }
WinForms Lượt xem:
Task vs ValueTask Lượt xem:
record Lượt xem:
Algo Lượt xem: