diff --git a/compendium/modules/w01-intro-lab.tex b/compendium/modules/w01-intro-lab.tex index 023b0740..18b07e29 100644 --- a/compendium/modules/w01-intro-lab.tex +++ b/compendium/modules/w01-intro-lab.tex @@ -10,7 +10,7 @@ \begin{Preparations} \item Repetera veckans föreläsningsmaterial. \item \DoExercise{\ExeWeekONE}{01}%Gör övning {\tt \ExeWeekONE} i kapitel \ref{exe:W01}. -\item Läs om Kojo i appendix \ref{appendix:kojo}. Kojo Desktop är förinstallerat på LTH:s datorer; om du vill installera Kojo Desktop på din egen dator, följ instruktionerna i \ref{appendix:ide:kojo:install}. +\item Läs om Kojo i appendix \ref{appendix:kojo}. \item Läs igenom hela laborationen nedan. Fundera på möjliga lösningar till de uppgifter som är markerade med en penna i marginalen. \item Hämta given kod via \href{https://github.com/lunduniversity/introprog/tree/master/workspace/}{kursen github-plats}. % \item Ladda hem och studera översiktligt detta dokument (25 sidor, det räcker att du bläddrar igenom dokumentet och får en uppfattning om hur Kojo kan användas): \\ ''Introduction to Kojo'' \url{http://www.kogics.net/kojo-ebooks#intro} @@ -104,6 +104,30 @@ \subsection{Obligatoriska uppgifter} % \Task Läs om hur du gör grafikprogram med Kojo i Appendix \ref{appendix:kojo} och övning {\tt \ExeWeekONE} i kapitel \ref{exe:W01}. +\Task \textit{Installera och starta Kojo}. Öppna terminalen och skriv in följande kommandon för att ladda filen \texttt{kojo.scala} från internet, spara den i katalogen \texttt{\textasciitilde/w01-kojo}, och starta Kojo. + +% \begin{minipage}{\textwidth} % wrap REPLnonum to make it not split at page-breaks +\vbox{ +\begin{REPLnonum} +> mkdir ~/w01-kojo +> cd ~/w01-kojo +> curl -sLO https://fileadmin.cs.lth.se/kojo.scala +> scala repl ~/w01-kojo/kojo.scala +\end{REPLnonum} +} +% \end{minipage} +\vbox{ % avoid page breaks +Nu borde du kunna skriva \texttt{activateCanvas()} i terminalen, trycka på ENTER, och se ett fönster dyka upp på skärmen. + +\begin{REPLnonum} +Welcome to Scala 3.7.3 (21.0.8, Java OpenJDK 64-Bit Server VM). +Type in expressions for evaluation. Or try :help. + +scala> activateCanvas() + +scala> +\end{REPLnonum} +} \Task \textit{Sekvens och repetition}. Rita en kvadrat med hjälp av \code+upprepa(n){ ??? }+ där du ersätter \code{n} med antalet repetitioner och \code{???} med de satser som ska repeteras. @@ -117,14 +141,19 @@ \subsection{Obligatoriska uppgifter} \Subtask Funktionen \code{System.currentTimeMillis} ingår i Javas standardbibliotek och ger ett heltal av typen \code{Long} med det nuvarande antalet millisekunder sedan midnatt den första januari 1970. Med Kojo-proceduren \code{sakta(0)} blir det ingen fördröjning när paddan ritar och utritningen sker så snabbt som möjligt. Prova nedan program och förklara vad som händer. \begin{Code} -sakta(0) -val n = 800 * 4 -val t1 = System.currentTimeMillis -upprepa(n){ upprepa(4){ fram; höger } } -val t2 = System.currentTimeMillis -println(s"$n kvadratvarv tog ${t2 - t1} millisekunder") +{ + sakta(0) + val n = 800 * 4 + val t1 = System.currentTimeMillis + upprepa(n): + upprepa(4): + fram + höger + val t2 = System.currentTimeMillis + println(s"$n kvadratvarv tog ${t2 - t1} millisekunder") +} \end{Code} -\noindent Om du kör Kojo Desktop är det bra att börja programmet med \code{sudda}. (Varför?) +%\noindent Det är bra att börja programmet med \code{sudda}. (Varför?) \Subtask\Pen Anteckna ungefär hur många kvadratvarv per sekund som paddan kan rita när den är som snabbast. Kör flera gånger eftersom den virtuella maskinen behöver ''värmas upp'' för att maskinkoden ska optimeras. Vissa körningar kan gå långsammare om skräpsamlaren behöver lägga tid på att frigöra minne. @@ -135,16 +164,21 @@ \subsection{Obligatoriska uppgifter} \begin{Code} sakta(100) var i = 0 -while (???) { fram; höger; i = ??? } +while ??? do + fram + höger + i = ??? \end{Code} \Subtask\Pen Vad är det för skillnad på variabler som deklareras med \code{val} respektive \code{var}? -\Subtask Rita en kvadrat igen, men nu med hjälp av en \code{for}-sats. Skriv ut värdet på den lokala variabeln \code{i} i varje loop-runda. - +\Subtask Rita en kvadrat igen, men nu med hjälp av en \code{for}-sats. Skriv ut värdet på den lokala variabeln \code{i} i varje loop-runda.\\ +\vbox{ \begin{Code} -for (i <- 1 to ???) { ??? } +for i <- 1 to ??? do + ??? \end{Code} +} \Subtask\Pen Går det att tilldela variabeln \code{i} ett nytt värde i loopen? @@ -154,7 +188,8 @@ \subsection{Obligatoriska uppgifter} \Subtask Rita en kvadrat igen, men nu med hjälp av \code{foreach}. Skriv ut loopvariabelns värde i varje runda. \begin{Code} -(1 to ???).foreach{ i => ??? } +(1 to ???).foreach: i => + ??? \end{Code} %\Subtask\Pen För var och en av de fyra repetitionskonstruktionerna du sett ovan, \code{upprepa}, \code{while}, \code{for} och \code{foreach}: skriv kod med penna på papper som skriver ut de första 100 jämna heltalen med blanktecken emellan: \code{2 4 6 8 10 12 ...} etc.\\ Vilken typ av loop tycker du är enklast att använda i detta fall? @@ -175,7 +210,9 @@ \subsection{Obligatoriska uppgifter} \Subtask Definiera en egen procedur som heter \code{kvadrat} med hjälp av nyckelordet \code{def} som vid anrop ritar en kvadrat med hjälp av en \code{for}-loop. \begin{Code} -def kvadrat = for (???) {???} +def kvadrat = + for ??? do + ??? \end{Code} @@ -192,8 +229,12 @@ \subsection{Obligatoriska uppgifter} \columnbreak \begin{Code} - def kvadrat = for (???) {???} - for (???) {???} + def kvadrat = + for ??? do + ??? + + for ??? do + ??? \end{Code} \end{multicols} @@ -238,11 +279,10 @@ \subsection{Obligatoriska uppgifter} \begin{Code} sakta(5000) -def move(key: Int): Unit = { +def move(key: Int): Unit = println("key: " + key) - if (key == 87) fram(10) - else if (key == 83) fram(-10) -} + if key == 87 then fram(10) + else if key == 83 then fram(-10) move(87); move('W'); move('W') move(83); move('S'); move('S'); move('S') @@ -251,13 +291,13 @@ \subsection{Obligatoriska uppgifter} \Subtask \label{subtask:keypress} Kör programmet nedan. Notera \code{activateCanvas()} för att du ska slippa klicka i ritfönstret innan du kan styra paddan. Anropet \code{onKeyPress(move)} gör så att \code{move} kommer att anropas då en tangent trycks ned. Lägg till kod i \code{move} som gör att tangenten A ger en vridning moturs med 5 grader medan tangenten D ger en vridning medurs 5 grader. Med \code{onKeyPress} bestämmer man vilken procedur som ska köras vid tangenttryck. \begin{Code} -sakta(0); activateCanvas() +sakta(0) +activateCanvas() -def move(key: Int): Unit = { +def move(key: Int): Unit = println("key: " + key) - if (key == 'W') fram(10) - else if (key == 'S') fram(-10) -} + if key == 'W' then fram(10) + else if key == 'S' then fram(-10) onKeyPress(move) \end{Code} @@ -333,13 +373,13 @@ \subsection{Frivilliga extrauppgifter} var isGridOn = false def toggleGrid = - if (isGridOn) { + if isGridOn then gridOff isGridOn = false - } else { + else gridOn isGridOn = true - } + \end{Code} \Subtask Gör så att när man trycker på tangenten X så sätter man omväxlande på och av koordinataxlarna. Använd en variabel \code{isAxesOn} och definiera en abstraktion \code{toggleAxes} som anropar \code{axesOn} och \code{axesOff} på liknande sätt som i föregående uppgift. @@ -389,7 +429,7 @@ \subsection{Frivilliga extrauppgifter} \Subtask\Pen Föreslå tre förändringar av programmet ovan (till exempel namnbyten) som gör att det blir lättare att läsa och förstå. -\Subtask Gör sök-ersätt av \code{gurka} till ett bättre namn. \emph{Tips:} undersök kontextmenyn i editorn i Kojo genom att högerklicka. Använd kortkommandot för Sök/Ersätt. +\Subtask Gör sök-ersätt av \code{gurka} till ett bättre namn. % \emph{Tips:} undersök kontextmenyn i editorn i Kojo genom att högerklicka. Använd kortkommandot för Sök/Ersätt. \Subtask Gör automatisk formatering av koden med hjälp av lämpligt kortkommando. Notera skillnaderna. Vilka autoformateringar gör programmet lättare att läsa? Vilka manuella formateringar tycker du bör göras för att öka läsbarheten? Ge funktionen \code{gurka} ett bättre namn. Diskutera läsbarheten med en handledare. @@ -397,23 +437,25 @@ \subsection{Frivilliga extrauppgifter} \Task \label{task:measuretime} \emph{Tidmätning.} Hur snabb är din dator? -\Subtask \label{task:timer} Skriv in koden nedan i Kojos editor och kör upprepade gånger med den gröna play-knappen. Tar det lika lång tid varje gång? Varför? +\Subtask \label{task:timer} Skriv in koden nedan i replen och kör upprepade gånger genom att skriva \code{main} i replen. Tar det lika lång tid varje gång? Varför? \begin{Code} -object timer { +object timer: def now: Long = System.currentTimeMillis var saved: Long = now def elapsedMillis: Long = now - saved def elapsedSeconds: Double = elapsedMillis / 1000.0 - def reset: Unit = { saved = now } -} + def reset: Unit = + saved = now // HUVUDPROGRAM: -timer.reset -var i = 0L -while (i < 1e8.toLong) { i += 1 } -val t = timer.elapsedSeconds -println("Räknade till " + i + " på " + t + " sekunder.") +def main = + timer.reset + var i = 0L + while i < 1e8.toLong do + i += 1 + val t = timer.elapsedSeconds + println("Räknade till " + i + " på " + t + " sekunder.") \end{Code} @@ -429,41 +471,43 @@ \subsection{Frivilliga extrauppgifter} \Subtask Ändra i koden i uppgift \ref{task:timer}) så att \code{while}-loopen bara kör 5 gånger. %Kör programmet med den \emph{gula} play-knappen. Scrolla i programspårningen och förklara vad som händer. Klicka på \code{CALL}-rutorna och se vilken rad som markeras i ditt program. -\Subtask Lägg till koden nedan i ditt program och försök ta reda på ungefär hur långt din dator hinner räkna till på en sekund för \code{Long}- respektive \code{Int}-variabler. Använd den gröna play-knappen. +\Subtask Lägg till koden nedan i ditt program och försök ta reda på ungefär hur långt din dator hinner räkna till på en sekund för \code{Long}- respektive \code{Int}-variabler. Skriv \code{räknaSnabbt} terminalen för att köra huvudprogrammet. \begin{CodeSmall} -def timeLong(n: Long): Double = { +def timeLong(n: Long): Double = timer.reset var i = 0L - while (i < n) { i += 1 } + while i < n do + i += 1 timer.elapsedSeconds -} -def timeInt(n: Int): Double = { +def timeInt(n: Int): Double = timer.reset var i = 0 - while (i < n) { i += 1 } + while i < n do + i += 1 timer.elapsedSeconds -} -def show(msg: String, sec: Double): Unit = { +def show(msg: String, sec: Double): Unit = print(msg + ": ") println(sec + " seconds") -} -def report(n: Long): Unit = { +def report(n: Long): Unit = show("Long " + n, timeLong(n)) - if (n <= Int.MaxValue) show("Int " + n, timeInt(n.toInt)) -} + if n <= Int.MaxValue then + show("Int " + n, timeInt(n.toInt)) // HUVUDPROGRAM, mätningar: - -report(Int.MaxValue) -for (i <- 1 to 10) report(4.26e9.toLong) +def räknaSnabbt = + report(Int.MaxValue) + for i <- 1 to 10 do + report(4.26e9.toLong) \end{CodeSmall} \Subtask Hur mycket snabbare går det att räkna med \code{Int}-variabler jämfört med \code{Long}-variabler? Diskutera gärna svaret med en handledare. -\Task Lek med färg i Kojo. Sök på internet efter dokumentationen för klassen \code{java.awt.Color} och studera vilka heltalsparametrar den sista konstruktorn i listan med konstruktorer tar för att skapa sRGB-färger. Om du högerklickar i editorn i Kojo och väljer ''Välj färg...'' får du fram färgväljaren och med den kan du välja fördefinierade färger eller blanda egna färger. När du har valt färg får du se vilka parametrar till \code{java.awt.Color} som skapar färgen. Testa detta i REPL: +\Task Lek med färg i Kojo. Sök på internet efter dokumentationen för klassen \code{java.awt.Color} och studera vilka heltalsparametrar den sista konstruktorn i listan med konstruktorer tar för att skapa sRGB-färger. +% Om du högerklickar i editorn i Kojo och väljer ''Välj färg...'' får du fram färgväljaren och med den kan du välja fördefinierade färger eller blanda egna färger.När du har valt färg får du se vilka parametrar till \code{java.awt.Color} som skapar färgen. +Testa detta i REPL: \begin{REPL} scala> val c = new java.awt.Color(124,10,78,100)