Göm menyn

TDP007 Konstruktion av datorspråk

Seminarie 1: Introduktion till Ruby

Syftet med det första seminariet är att ni ska bli bekanta med språket Ruby och arbetssättet för laborationer och seminarier i kursen.

Vad ska man tänka på?

Innan ni börjar med uppgifterna, läs igenom Seminariesidan. Den förklarar hur ni ska redovisa era lösningar och hur ni ska förbereda er för seminaret. Förutom lösningar på uppgifter ska ni även lämna in enhetstester och utvecklarblogg. Läs igenom anvisningarna för dessa också.

Inför det första seminariet ska ni lösa ett antal mindre uppgifter i Ruby. Ni ska redovisa minst två från vardera av de fyra avsnitten nedan, totalt alltså minst åtta uppgifter.


Avsnitt 1: Iteratorer

I dessa uppgifter ska ni använda eller konstruera iteratorer, d.v.s. funktioner som tar block av programkod och applicerar på varje element i en array, hash eller liknande datastruktur. Ni kan läsa mer om iteratorer i kursbokens kapitel 4.

Uppgift 1: Skriv en iterator-funktion n_times(n) som anropar det givna blocket n gånger. Skriv dessutom en iterator-klass Repeat som instansieras med ett tal. Klassen ska ha en metod each som tar ett block och anropar det så många gånger som angavs när objektet skapades. Exempel:

>> n_times(3) { puts "Hello!" } Hello! Hello! Hello! => 3 >> do_three = Repeat.new(3) #<Repeat:0xe7288 @n=3> >> do_three.each { puts "Hooray!" } Hooray! Hooray! Hooray! => 3

Uppgift 2: Skriv Ruby-kod som på en enda rad beräknar 20! med hjälp av funktionen Range#inject. Generalisera därefter lösningen och skriv en funktion factorial som beräknar fakulteten av ett positivt heltal med samma lösningsmetod.

Uppgift 3: Skriv en funktion som tar en array med strängar och returnerar den längsta av dem. Exempel:

>> longest_string ["apelsin", "banan", "citron"] => "apelsin"

Uppgift 4: Skriv en funktion find_it som tar en array av strängar och ett block. Blocket ska ta två parametrar och returnera ett sanningsvärde. Funktionen find_it ska kunna användas för att implementera longest_string, shortest_string och andra liknande funktioner enbart genom att ändra blocket som man skickar in. Exempel på hur man löser samma problem som longest_string men med find_it:

>>> find_it(["apelsin", "banan", "citron"]) { |a,b| a.length > b.length } => "apelsin"


Avsnitt 2: Åtkomstfunktioner

I dessa uppgifter ska ni öva på att skapa klasser och komma åt deras attribut på olika sätt. Läs mer om attribut i kursbokens kapitel 3.

Uppgift 5: Skapa en klass PersonName som har följande attribut:

  • name som innehåller personens förnamn (sträng)
  • surname som innehåller personens efternamn (sträng)
  • fullname som i praktiken är "#{surname} #{name}"

Attributet fullname ska vara ett virtuellt attribut. Det ska alltså inte lagras i objektet, utan det ska bara finnas åtkomstfunktioner som gör att det ser ut som att det finns ett sådant attribut. Förutom att konstruera en "getter" fullname som returnerar hela namnet ska ni också konstruera en "setter" fullname= som sätter värdena på name och surname, t.ex. genom att använda String#split.

Uppgift 6: Skapa en klass Person som har följande attribut:

  • age som innehåller personens ålder i år (heltal)
  • birthyear som innehåller personens födelseår (heltal)
  • name som innehåller personens namn, lagrat i ett objekt av klassen PersonName från föregående uppgift

Person-klassens konstruktor ska kunna ta in förnamn, efternamn och ålder, samtliga valfria. Personens ålder och födelseår ska alltid stämma överens. Det innebär att om man ändrar födelseåret ska även åldern ändras, och tvärtom. Titta på klasserna Date och DateTime som finns i date-modulen för att hämta innevarande år.


Avsnitt 3: Utökning av existerande klasser

I dessa uppgifter ska ni få öva på att utöka klasser med nya metoder. Alla klasser i Ruby kan utökas, även de inbyggda, och man kan också göra utökningar enbart för enskilda objekt.

Uppgift 7: Utöka klassen Integer med en metod fib som beräknar motsvarande Fibonacci-tal. Fibonacci-serien fungerar så att tal nummer n är summan av talen n-1 och n-2. De två första talen är båda 1.

Uppgift 8: Utöka klassen String med en metod acronym som returnerar en sträng som består av begynnelsebokstäverna i de ord som finns i strängen (som stora bokstäver). Exempel:

>> "Laugh out loud".acronym => "LOL" >> "Do what I mean!!".acronym => "DWIM"

Uppgift 9: Utöka klassen Array med en metod rotate_left som roterar innehållet i arrayen åt vänster (d.v.s. flyttar element från början till slutet). Metoden ska kunna ta ett heltal som anger antalet steg, med 1 som default. Exempel:

>> [1,2,3].rotate_left => [2, 3, 1] >> [1,2,3].rotate_left(3) => [1, 2, 3]


Avsnitt 4: Reguljära uttryck

I dessa uppgifter ska ni använda reguljära uttryck som är ett slags mönster för att matcha innehållet i strängar. Läs mer om reguljära uttryck i lärobokens kapitel 5.

Uppgift 10: Skriv en funktion som med hjälp av ett reguljärt uttryck kan hämta fram användarnamnet ur en sträng på formen "USERNAME: Brian". Funktionen ska fungera oavsett vad som står först på raden, så länge det är en följd av små eller stora bokstäver innan kolon. I exemplet ovan så bör resultatet bli "Brian".

Uppgift 11: Skriv en funktion som hämtar namnen på alla HTML-taggar i ett dokument. Varje tag som förekommer i arrayen skall endast förekomma en gång, det skall alltså vara en unik array. Exempel:

>> require 'open-uri.rb' => true >> html = URI.open("http://www.google.com/") { |f| f.read } => "<html><head><title>Google</title> ..." >> tag_names(html) => [["html"], ["head"], ["title"], ...]

De två första raderna i exemplet ovan ser till att hela webbsidan läses in till en enda sträng som man sedan kan bearbeta med funktionen tag_names.

Uppgift 12: Konstruera en funktion som tar reda på om en sträng innehåller ett godkänt svenskt registreringsnummer. Ni behöver inte ta hänsyn till att vissa kombinationer är förbjudna, utan det räcker om ni ser till att endast godkända bokstäver är med. Funktionen ska returnera det giltiga registreringsnumret, alternativt false om inget sådant finns. Exempel:

>> regnr("Min bil heter FMA297.") => "FMA297" >> regnr("XQT784") => false

Reglerna för registreringsnummer finns på t.ex. på Wikipedia.


Sidansvarig: Pontus Haglund
Senast uppdaterad: 2024-01-23