Escriu per cercar…

Algoritme

Un algoritme és un programa que pot executar diferents blocs de codi en funció de si es compleixen, o no es compleixen, unes condicions el número de vegades que tu vulguis.

Introducció

Tal com has vist a Computació, un programa pot executar qualsevol mena de fórmula matemàtica.

Però a part d’això, amb el que coneixes fins ara, no es pot fer gaire cosa més.

Tots els algoritmes es basen en una condició que només pot tenir dos valors: cert o fals.

En Typescript tens els tipus boolean que només pot tenir dos valors: true o false

Selecció

Condició

Una variable de tipus boolean ens permet executar un tros de codi si es compleix una condició.

Això es fa amb l’expressió if.

La sentència if (...) avalua la condició dins els parèntesis, i si el resultat és cert (true), executa un bloc de codi.

Crea el fitxer main.ts:

ts
let isDone: boolean = true

if (isDone) {
    console.log("Ben fet!")
}

console.log("Adeu!")

Si executes el codi pots veure que com que isDone és true, s’executa la sentència console.log("Ben fet!"):

shell
$ deno.exe .\main.ts
Ben fet!
Adeu!

En canvi, si modifiques el codi i dius que isDone és false:

ts
let isDone: boolean = false

if (isDone) {
    console.log("Ben fet!")
}
console.log("Adeu!")

La sentència console.log("Ben fet!") no s’executa:

shell
$ deno.exe .\main.ts
Adeu!

A continuació tens el diagrama d’execució:

Comparació

Els operadors de comparació comparen dos valors i retornen un valor de tipus boolean: true o false.

OperadorExempleExplicació
==a == ba és igual a b
!=a != ba no és igual a b
>a > ba és més gran que b
<a > ba és menys gran que b
>=a >= ba és més gran o igual que b
<=a <= ba és menys gran o igual que b

Per exemple:

ts
console.log(2 > 1)  // true 
console.log(2 == 1) // false
console.log(2 != 1) // true

Si intentes comparar dos tipus diferents, Typescript et diu que t’estas equivocant:

ts
let result: boolean = "eee" > 4

Error. Operator '>' cannot be applied to types 'string' and 'number'

El resultat d’una comparació és pot assignar a una variable, igual que qualsevol valor:

ts
let result: boolean = 5 > 4 // assignar el resultat de la comparació
console.log(result); // true

Si intentes comparar dos variables amb tipus diferent, Typescript et diu que és un error:

ts
let a: number
let b: string
console.log( a == b)

Error. This comparison appears to be unintentional because the types 'number' and 'string' have no overlap.

Si compares un valor amb un variable que té valor null, el resultat és false:

ts
let dog : string | null = null
console.log(dog == "Idefix")

else

Molts cops no només has d’executar codi si es compleix una condició, també quan no es compleix aquesta condició (encara que només sigui per dir a l’usuari que la condició no es compleix).

Per això a un if se li pot afegir un else.

Per exemple, aquí tens un programa que permet a l’usuari comprar un drac volador si money és major de 100 monedes d’or 🐉

ts
let money = 230

if (money > 100) {
    alert("Tens un 🐉")
} else {
    alert("El preu del 🐉 és de 100 🪙")
}

console.log("Adeu 👋")

Si executes el codi, pots comprar un drac volador:

shell
> deno.exe .\main.ts
Tens un 🐉 [Enter] 
Adeu 👋

A continuació tens el diagrama d’execució del codi:

A continuació modifica el codi per tal que demani a l’usuari quantes monedes ofereix:

Show solution
ts
let money: number = Number(prompt("Quantes monedes ofereixes 🪙?", "0"))
if (money > 100) {
  alert("Tens un 🐉")
} else {
  alert("El preu del 🐉 és de 100 🪙")
}

console.log("Adeu 👋")

else if

De vegades vols provar més d’una condició. La clàusula else if et permet fer-ho.

Per exemple:

ts
let year = Number(prompt('¿En qué año fue publicada la especificación ECMAScript-2015?', "0"))

if (year < 2015) {
    alert('Muy poco...');
} else if (year > 2015) {
    alert('Muy Tarde');
} else {
    alert('¡Exactamente!');
}

Al codi de dalt, TypeScript:

  • Primer comprova si year < 2015.
  • Si això és fals, continua amb la condició següent year > 2015.
  • Si aquesta també és falsa, mostrarà l’última alert.

Hi podria haver més blocs else if.

Operador ternari ?

De vegades necessites que el valor que assignes a una variable depengui d’alguna condició.

Per exemple:

ts
let age = Number(prompt('¿Qué edad tienes?', "0"))

let accessAllowed: string
if (age > 18) {
  accessAllowed = "Por supuesto!"
} else {
  accessAllowed = "Ni en sueños!"
}

alert(accessAllowed)

L’“operador condicional” et permet fer-ho d’una forma més curta i simple.

L’operador es representa amb el signe d’interrogació ?.

La sintaxi és:

ts
let result = condition ? value1 : value2;

S’avalua condition: si és certa retorna value1, i si no, value2.

Per exemple:

ts
let age = Number(prompt('¿Qué edad tienes?', "0"))

let accessAllowed = (age > 18) ? "Por supuesto!" : "Ni en sueños!"
alert(accessAllowed)

Múltiples ?

Una seqüència d’operadors d’interrogació ? pot retornar un valor que depèn de més d’una condició.

Per exemple:

ts
let age = Number(prompt('¿edad?', "18"))

let message =
    (age < 3) ? '¡Hola, bebé!' :
        (age < 18) ? '¡Hola!' :
            (age < 100) ? '¡Felicidades!' :
                '¡Qué edad tan inusual!'

alert(message)

Al principi pot costar entendre què està passant.

Però si t’hi fixes bé, veuràs que només és una seqüència ordinària de condicions:

  • El primer signe d’interrogació comprova si age < 3.
  • Si és cert, retorna '¡Hola, bebé!'. Si no, continua amb l’expressió que hi ha després dels dos punts :, que comprova si age < 18.
  • Si és cert, retorna '¡Hola!'. Si no, continua amb l’expressió que hi ha després dels dos punts següents :, que comprova si age < 100.
  • Si és cert, retorna '¡Felicidades!'. Si no, continua amb l’expressió que hi ha després dels dos punts :, que retorna '¡Qué edad tan inusual!'.

Aquí ho pots veure amb if..else:

ts
let age = Number(prompt('¿edad?', "18"))

let message: string
if (age < 3) {
    message = '¡Hola, bebé!'
} else if (age < 18) {
    message = '¡Hola!'
} else if (age < 100) {
    message = '¡Felicidades!'
} else {
    message = '¡Qué edad tan inusual!'
}

alert(message)

Activitat

1.- Escriu un script que et pregunta l’edat, i et diu que pots votar si tens més de 17 anys:

Show solution
ts
let edat: number | null = Number(prompt("Quina edat tens?"))

if (edat > 17) {
  alert("Pots votar!")
}

2.- Modifica l’script perquè a més de dir-te que encara no tens edat per votar, et digui quants anys et falten per poder votar.

Show solution

3.- Que passa si l’usuari et diu que té -555 anys?

Show solution

4.- Utilitzant el constructor if..else, escriu un codi que demani un número amb un prompt i que després mostri en un alert:

  • 1, si el valor és més gran que zero,
  • -1, si és més petit que zero,
  • 0, si és igual a zero.
Show solution
ts
    let value = Number(prompt('Escribe un número', "0"))

    if (value > 0) {
    alert(1);
} else if (value < 0) {
    alert(-1);
} else {
    alert(0);
}
    ```

5.- Reescriu aquesta condició if amb l’operador ternari ?:

ts
let a = 5
let b = 8 

let result: string

if (a + b < 4) {
  result = 'Debajo'
} else {
  result = 'Encima'
}
Show solution
ts
let a = 5
let b = 8

let result = (a + b < 4) ? 'Debajo' : 'Encima'

6.- Reescriu el if..else utilitzant operadors ternaris múltiples ?.

ts
let login :string | null = null

let message;

if (login == 'Empleado') {
  message = 'Hola'
} else if (login == 'Director') {
  message = 'Felicidades'
} else if (login == null) {
  message = 'Sin sesión'
} else {
  message = ''
}

console.log(message)
Show solution
ts
let login: string | null = null

let message =
(login == 'Empleado') ? 'Hola' :
(login == 'Director') ? 'Felicidades' :
(login == null) ? 'Sin sesión' : ''

console.log(message)

Operadors lògics

|| OR

L’operador OR es representa amb dues barres verticals:

ts
let result: boolean = a || b;

Si qualsevol dels seus arguments és true, retorna true; si no, retorna false.

Hi ha quatre combinacions lògiques possibles:

ts
console.log(true || true)   // true 
console.log(false || true)  // true
console.log(true || false)  // true
console.log(false || false) // false

Com pots veure, el resultat sempre és true excepte quan tots dos operands són false.

La majoria de vegades, l’OR || s’utilitza dins d’un if per comprovar si alguna de les condicions donades és true.

Per exemple:

ts
let hour = 9

if (hour < 10 || hour > 18) {
    alert('La oficina esta cerrada')
}

Pots posar-hi més condicions:

ts
let hour = 12
let isWeekend = true

if (hour < 10 || hour > 18 || isWeekend) {
    alert("La oficina esta cerrada.") // És cap de setmana
}

Donats múltiples valors aplicats a l’operador OR:

ts
let result: boolean = value1 || value2 || value3

L’operador OR || fa el següent:

  • Avalua els operands d’esquerra a dreta.
  • Per a cada operand, si el resultat és true, s’atura i retorna true.
  • Si tots els operands eren false, retorna false.

&& AND

L’operador AND es representa amb dos ampersands &&:

ts
let result: boolean = a && b

L’AND retorna true si tots dos operands són valors certs, i false en qualsevol altre cas.

ts
console.log(true && true)   // true
console.log(false && true)  // false
console.log(true && false)  // false
console.log(false && false) // false

Un exemple amb if:

ts
let hour = 12
let minute = 30

if (hour == 12 && minute == 30) {
    alert("La hora es 12:30")
}

Donats múltiples valors aplicats a l’operador AND:

ts
let result: boolean = value1 && value2 && value3;

L’operador AND && fa el següent:

  • Avalua els operands d’esquerra a dreta.
  • Per a cada operand, si el resultat és false, s’atura i retorna false.
  • Si tots els operands eren valors certs, retorna true.

La precedència de l’operador AND && és més alta que la de l’OR ||.

Així doncs, el codi a && b || c && d és bàsicament el mateix que si les expressions && estiguessin entre parèntesis: (a && b) || (c && d).

! (NOT)

L’operador booleà NOT es representa amb un signe d’exclamació !.

La sintaxi és força simple:

ts
let result: boolean = !value

L’operador accepta un sol argument i fa el següent: retorna el valor contrari.

Per exemple:

ts
console.log(!true)    // false
console.log(!(5 > 0)) //false

La precedència del NOT ! és la més alta de tots els operadors lògics, així que sempre s’executa primer, abans que && o ||.

Activitat

1.- Escriu una condició if per comprovar que age està entre 40 i 60, tots dos inclosos.

“Inclosos” vol dir que age pot arribar a ser un dels extrems, 40 o 60.

Show solution
ts
let age = 50

if (age >= 40 && age <= 60)
alert("You are middle-aged")

2.- Escriu una condició if per comprovar que age NO està entre 40 i 60, tots dos inclosos.

Crea dues variants: la primera fent servir el NOT !, i la segona sense fer-lo servir.

Show solution
ts
let age = 90

if (!(age >= 40 && age <= 60))
alert("You aren't middle age")

if (age > 60 || age < 40)
alert("You aren't middle age")

3.- Escriu un codi que primer pregunti el nom de l’usuari, i si aquest és admin, pregunti per la contrasenya, i si aquesta és password, doni la benvinguda a l’ususari.

Show solution
ts
    let userName = prompt("Who are you?")

    if (userName != "admin")
    alert("I don't know you")
    else {
    let pass = prompt("Password?")
    if (pass != "password")
    alert("Bad password")
    else
    alert("Welcome!")
}
    ```

Repetició

Normalment necessites repetir accions.

Per exemple, mostrar els elements d’una llista un darrere l’altre, o simplement executar el mateix codi per a cada número de l’1 al 10.

Els bucles són una manera de repetir el mateix codi diverses vegades.

While

El bucle while (mentre) té la sintaxi següent:

ts
while (condition) {
  // codi
  // anomenat "cos del bucle"
}

Mentre la condició condition sigui certa, s’executarà el codi del cos del bucle.

Per exemple, el bucle de sota imprimeix i mentre es compleixi i < 3:

ts
let i: number = 0
while (i < 3) { // mostra 0, després 1, després 2
    console.log(i)
    i += 1
}
shell
$ deno main.ts
0
1
2

Cada execució del cos del bucle s’anomena iteració. El bucle de l’exemple de dalt fa 3 iteracions.

Si al codi de dalt hi faltés i += 1, el bucle es repetiria (en teoria) eternament. A la pràctica, el navegador té maneres d’aturar aquests bucles desbocats; i al costat del servidor, pots matar el procés.

ts
let i: number = 0
while (i < 3) { 
    console.log(i)
}

El bucle “do…while”

La comprovació de la condició es pot moure sota el cos del bucle amb la sintaxi do..while:

ts
do {
  // cos del bucle
} while (condition)

El bucle primer executa el cos, després comprova la condició, i mentre sigui certa, l’executa un cop i un altre.

Per exemple:

ts
let guess: string | null
do {
    guess = prompt("Guess")
} while (guess != "toto")

A continuació tens un exemple d’execució:

shell
$ deno test.ts
Guess fofo
Guess 
Guess toto

Aquesta sintaxi només l’has de fer servir quan vols que el cos del bucle s’executi com a mínim un cop, tant si la condició és certa com si no.

Trencar el bucle

Normalment se surt d’un bucle quan la condició es torna falsa.

Però pots forçar-ne la sortida en qualsevol moment amb la directiva especial break.

Per exemple, en aquest bucle mai s’imprimeix res a la consola:

ts
let i: number = 0
while (i < 10) {
    i += 1
    break
    console.log(i)
}
console.log(`i == ${i}`)

I només s’executa 1 cop!

ts
$ deno test.ts
i == 1

A continuació tens un exemple en què es demana a l’usuari que endevini un número:

ts
const guess = 5
let tries = 3

while (tries > 0) {

    let n : number | null = Number(prompt("Número"))
    
    if (n == guess) {
        console.log("Correcte!")
        break
    }

    i =-1
}

Pots veure que el bucle acaba abans dels 3 intents perquè l’usuari ha endevinat el número.

shell
$ deno test.ts
Número 3
Número 5
Correcte!

La combinació “bucle infinit + break quan calgui” és ideal en situacions on la condició del bucle s’ha de comprovar no al principi ni al final del bucle, sinó al mig o fins i tot en diversos punts del cos.

Continuar amb la iteració següent

La directiva continue atura la iteració actual i força el bucle a començar-ne una de nova (si la condició ho permet).

Per exemple, en aquest bucle mai s’imprimeix res a la consola:

ts
let i: number = 0
while (i < 10) {
    i += 1
    continue
    console.log(i)
}
console.log(`i == ${i}`)

Però s’executa 10 vegades!

shell
$ deno test.ts
i == 10

A continuació tens un bucle que va sumant números mentre l’usuari no entri cap valor:

ts
let sum: number = 0
while (true) {

    let input: string | null = prompt("Número")

    if (input == null)
        break

    sum += Number(input)
    console.log(sum)
}

Pots veure que el programa va sumant tret que l’usuari premi “enter” sense cap valor:

shell
$ deno test.ts
Número 34
34
Número 56
90
Número 

El problema és que si l’usuari introdueix un string que no es pot transforma en number

shell
$ deno test.ts
Número tres
NaN
Número 45
NaN
Número

Tot és un NaN a partir de llavors.

Modifica el codi per verificar si l’entrada és NaN, i si es cert, continuar amb la propera iteració:

ts
let sum  = 0
while (true) {

    let input = prompt("Número")
    
    if (input == "")
        break
    
    let n = Number(input)
    if (Number.isNaN(n))
        continue

    sum += Number(input)
    console.log(sum)
}

Pots verificar que tot el que no sigui un número s’ignora:

shell
$ deno test.ts
Número tres
Número 5
5
Número 

Activitats

Task

Demana a l’usuari un número entre 1 i 7 i mostra el nom del dia de la setmana (1 = dilluns, 7 = diumenge). Si el número no està entre 1 i 7, mostra un missatge d’error.

Show solution
ts
let day = Number(prompt("Number from 1 to 7?", "1"));
if (day == 1) console.log("Monday");
else if (day == 2) console.log("Tuesday");
else if (day == 3) console.log("Wednesday");
else if (day == 4) console.log("Thursday");
else if (day == 5) console.log("Friday");
else if (day == 6) console.log("Saturday");
else if (day == 7) console.log("Sunday");
else console.log("Invalid day");
Task

Demana una nota del 0 al 10 i mostra:

  • "Fail" si la nota és inferior a 5,
  • "Pass" si va de 5 (inclòs) a 6.9,
  • "Good" si va de 7 a 8.9,
  • "Excellent" si va de 9 a 10.

Fes-ho primer amb if..else if..else

Show solution
ts
let grade = Number(prompt("Grade (0–10)?", "0"));
let message: string;
if (grade < 5) message = "Fail";
else if (grade < 7) message = "Pass";
else if (grade < 9) message = "Good";
else message = "Excellent";
console.log(message);

i després reescriu-ho amb una expressió ternària encadenada.

Show solution
ts
let grade = Number(prompt("Grade (0–10)?", "0"));

let message = (grade < 5) ? "Fail" : (grade < 7) ? "Pass" : (grade < 9) ? "Good" : "Excellent";
console.log(message);
Task

Tens dos booleans:

ts
let hasTicket: boolean = true
let isVIP: boolean = false

Escriu un if que imprimeixi "Can enter" si la persona té entrada o és VIP, i "Cannot enter" en cas contrari.

Show solution
ts
if (hasTicket || isVIP) { console.log("Can enter") } else { console.log("Cannot enter") }

Reescriu-ho amb una sola expressió ternària.

Show solution
ts
let message = (hasTicket || isVIP) ? "Can enter" : "Cannot enter"
console.log(message)
Task

Imprimeix tots els números de l’1 al 20 que siguin parells fent servir un bucle while.

Show solution
ts
    let i: number = 1;
    while (i <= 20) {
    if (i % 2 == 0) {
    console.log(i);
}
    i += 1;
}
    ```
Task

Amb un bucle do..while, demana a l’usuari que escrigui "yes" per continuar. Atura’t només quan l’usuari escrigui "no".

Show solution
ts
let answer: string | null

do {
    answer = prompt('Write "yes" to continue, "no" to stop', "yes")
} while (answer != "no")

console.log("Finished")
Task

Crea un programa que vagi demanant números i que només sumi els positius a un total.

Atura’t quan l’usuari premi “Enter” sense escriure res (null), o escrigui 0.

Fes servir continue per ignorar els números negatius.

Show solution
ts
let sum: number = 0;
while (true) {
    let input: string | null = prompt("Number (0 or empty to stop)", "");
    if (input == null || input == "") {
        break;
    }
    let n: number = Number(input);
    if (Number.isNaN(n)) continue;
    if (n == 0) break;
    if (n < 0) continue;
    sum += n;
    console.log("Current sum:", sum);
}
console.log("Final sum:", sum);
Task

Fes servir un bucle while (true) amb break per anar demanant contrasenyes fins que l’usuari n’escrigui la correcta ("1234").

  • Si l’usuari prem “Cancel·la” (null), atura el bucle i imprimeix "Cancelled".
  • Si l’usuari introdueix la contrasenya correcta, imprimeix "Access granted" i atura’t.
Show solution
ts
const password = "1234";
while (true) {
    let input: string | null = prompt("Password?", "");
    if (input == null) {
        console.log("Cancelled");
        break;
    }
    if (input == password) {
        console.log("Access granted");
        break;
    }
    console.log("Wrong password, try again");
}
Task

Crea un petit sistema de login i menú:

  1. Demana un nom d’usuari i una contrasenya.
    • El nom d’usuari correcte és "admin" i la contrasenya correcta és "secret".
  2. Si un dels dos és incorrecte, imprimeix "Access denied" i atura’t.
  3. Si tots dos són correctes, mostra un menú dins d’un bucle:
    • Demana a l’usuari que triï:
      • 1 – Mostrar l’hora actual (pots fer simplement console.log("12:00"))
      • 2 – Jugar a endevinar un número (de l’1 al 10, 3 intents).
      • 0 – Sortir.
  4. Fes servir if/else, operadors lògics i bucles (while + break) per implementar-ho.
Show solution
ts
let user = prompt("User?", "");
let pass = prompt("Password?", "");

if (user != "admin" || pass != "secret") {
    console.log("Access denied");
} else {
    console.log("Welcome!");

    while (true) {
        let choice = prompt("Menu: 1-Time  2-Guess game  0-Exit");

        if (choice == null) {
            break;
        }

        if (choice == "0") {
            console.log("Bye!");
            break;
        } else if (choice == "1") {
            console.log("Time: 12:00");
        } else if (choice == "2") {
            const secret = 7;
            let tries = 3;

            while (tries > 0) {
                let input = prompt("Guess (1–10)");
                if (input == null) break;

                let n = Number(input);
                if (Number.isNaN(n)) {
                    console.log("Not a number");
                    continue;
                }

                if (n == secret) {
                    console.log("Correct!");
                    break;
                } else if (n < secret) {
                    console.log("Too small");
                } else {
                    console.log("Too big");
                }

                tries -= 1;
                console.log(`Tries left: ${tries}`);
            }
        } else {
            console.log("Unknown option");
        }
    }
}
Task

Crea un programa que demani a l’usuari endevinar un número de l’1 al 100, i li digui si l’ha encertat, o si el número és més gran o més petit.

Show solution
Task

Escriu un codi que et pregunti la data de naixement i torni el símbol astral.

Show solution
ts
const dia = Number(prompt("Dia? ", "1"))
const mes = Number(prompt("Mes? ","1"))

const data = mes * 100 + dia

const astral = data < 120 ? "Capricornio" :
data < 220 ? "Acuario" :
data < 321 ? "Pisicis":
data < 420 ? "Aries":
data < 521 ? "Tauro":
data < 621 ? "Géminis":
data < 723 ? "Cáncer":
data < 823 ? "Leo":
data < 932 ? "Virgo":
data < 1023 ? "Libra":
data < 1122 ? "Escorpio":
data < 1222 ? "Sagitario":
data < 1232 ? "Capricornio": "Ni idea!"

console.log(astral)