Code Kata: staňte sa lepším programátorom

Vše okolo vývoje aplikací pro platformy Windows Phone a Windows 10 Mobile
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Kata je cvičenie v karate, ktoré sa opakuje stále dookola a každým opakovaním sa vaše schopnosti mierne zlepšujú. Princíp Code Katas je podobný, každá Code Kata je krátke 30-60 minútové cvičenie. Niektoré cvičenia zahrňujú programovanie a môžu byť vyriešené rôznymi spôsobmi, niektoré vyžadujú rozmýšľanie o problémom spojených s programovaním.

Code Katas existuje veľké množstvo pre rôzne programovacie jazyky (viď napríklad tento zoznam alebo tento web), vo všeobecnosti však nezáleží, v akom jazyku dané cvičenie riešite.

String Calculator

  • 1. Create a simple String calculator with a method int Add(string numbers)
    • a. The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0) for example “” or “1” or “1,2”
      b. Start with the simplest test case of an empty string and move to 1 and two numbers
      c. Remember to solve things as simply as possible so that you force yourself to write tests you did not think about
      d. Remember to refactor after each passing test
    2. Allow the Add method to handle an unknown amount of numbers
    3. Allow the Add method to handle new lines between numbers (instead of commas).
    • a. the following input is ok: “1\n2,3” (will equal 6)
      b. the following input is NOT ok: “1,\n” (not need to prove it - just clarifying)
    4. Support different delimiters
    • a. to change a delimiter, the beginning of the string will contain a separate line that looks like this: “//[delimiter]\n[numbers…]” for example “//;\n1;2” should return three where the default delimiter is ‘;’ .
      b. the first line is optional. all existing scenarios should still be supported
    5. Calling Add with a negative number will throw an exception “negatives not allowed” - and the negative that was passed.if there are multiple negatives, show all of them in the exception message
Celé cvičenie by vám nemalo zabrať viac ako 30 minút. Úloha je to celkom jednoduchá, vymyslieť elegantné riešenie však nie je tak jednoduché, ako sa na prvý pohľad môže zdať.

Moje riešenie

F#

Kód: Vybrat vše

open System

let MakeList (s:string)=
    if (s.StartsWith "//" ) then
       let (parts:string array) = Array.ofSeq(s.Split([|'\n'|],2))
       let delims = [|parts.[0].Replace("//","")|]
       List.ofSeq(parts.[1].Split(delims, StringSplitOptions.None))
    else          
        List.ofSeq(s.Split [|',';'\n'|])

let Add (s:string)=    
   if (String.IsNullOrEmpty(s)) then 0
   else         
        let numbers = List.map (fun n->int n) (MakeList s)
        let negatives = List.filter (fun n -> n < 0) numbers
        if (negatives.Length>0) then
            failwith ("negatives not allowed "+ (List.reduce (fun acc elem -> acc+","+elem) (List.map (fun n->n.ToString()) negatives)))
        else 
            List.reduce (fun acc elem -> acc + elem) numbers
C#

Kód: Vybrat vše

public IEnumerable MakeList(string s)
{	
    if (s.StartsWith("//"))
    {
        var parts = s.Split(new string[]{"\n"},StringSplitOptions.None);
        var delims = new string[]{parts[0].Replace("//","")};	
        return parts[1].Split(delims,StringSplitOptions.None).Select(l=>Int32.Parse(l));	
    }
        return s.Split(new char[]{',','\n'}).Select(l=>Int32.Parse(l));	
    }
     
 public int Add(string s)
{
    if (String.IsNullOrEmpty(s)) return 0;
    
    var numbers = MakeList(s);
    var negatives = numbers.Where(l=> l < 0);
    if (negatives.Any())
    {
        throw new ArgumentException("Negatives not allowed "+String.Join(",",negatives.Select(l=>l.ToString()).ToArray()));
    }
    return numbers.Aggregate(0, (acc,elem) => acc+elem);
 }
Máte riešenie v C#, F# alebo akomkoľvek inom jazyku? Podeľte sa o neho.
Martin Suchan
smartmaniak
smartmaniak
Příspěvky: 1138
Registrován: pát bře 11, 2011 10:48
Zařízení: Nokia Lumia 925
Bydliště: Praha

Code Kata: staňte sa lepším programátorom

Příspěvek od Martin Suchan »

Reseni v v C# je pekne a temer optimalni - Linq to umi dobre zkratit, jen mam pocit, ze v pripade alternativniho delimetru to nebude fungovat, pokud tam je vice nez jedno zalomeni radku

Kód: Vybrat vše

return parts[1].Split(delims,StringSplitOptions.None).Select(l=>Int32.Parse(l));   
Toto vrati jen cisla z druheho radku a dalsi uz ignoruje, spravne ma byt

Kód: Vybrat vše

var parts = s.Split(new []{"\n"}, 2, StringSplitOptions.None);  
Jinak pro zacatecniky doporucuji vyzkouset techto 6 jednoduchych Kata - vcera jsem se na to na hodinku zasekl :) Je tam interaktivni validace primo na webu, jen pozor na nekonecne cykly, to nemaji osetrene 8-)
http://codingkata.net/Katas" onclick="window.open(this.href);return false;
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Na to, že sa tu na fóre každý hrá na wp7 programátora, tu asi ozajstných programátorov veľa nebude :)
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Vážne sa nenájde nikto, kto by zverejnil svoje riešenie? Zaujíma ma, akým štýlom programujete.
Martin Suchan
smartmaniak
smartmaniak
Příspěvky: 1138
Registrován: pát bře 11, 2011 10:48
Zařízení: Nokia Lumia 925
Bydliště: Praha

Code Kata: staňte sa lepším programátorom

Příspěvek od Martin Suchan »

Mel jsi to svoje zverejnit az po tydnu, takhle se kazdy kouknul na vysledek a dal uz ho to nemotivovalo :)
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

No riešenie je jasné, ide o to, ako ho napíšeš. Ak by si to niekto chcel vyriešiť, tak si riešenie neprečíta :) Aj tak si myslím, že tomu F# tu veľa ľudí nerozumie a ani môjmu C# štýlu :)
Martin Suchan
smartmaniak
smartmaniak
Příspěvky: 1138
Registrován: pát bře 11, 2011 10:48
Zařízení: Nokia Lumia 925
Bydliště: Praha

Code Kata: staňte sa lepším programátorom

Příspěvek od Martin Suchan »

Tvuj styl C# mi prijde v pohode, mozna rozepsat to na vice radku pro prehlednost by neuskodilo :)
U toho F# mam ale pocit, ze zatim jen prepisujes C# syntaxi do F#. F# ma hodne vlastnich konstruktu a pristupu k reseni problemu. Treba nekonecna fibonacciho posloupnost se da napsat na jeden radek, coz v C# das dost tezko:

Kód: Vybrat vše

// generate an infinite Fibonacci sequence
let fibSeq = Seq.unfold (fun (a,b) -> Some( a+b, (b, a+b) ) ) (0,1)
// take the first few numbers in the sequence and convert the sequence to a list
let fibList = fibSeq |> Seq.takeWhile (fun x -> x<=400 ) |> Seq.toList
Nekde bych mozna vystrachal svoji praci v F# - implementace asi 10 kryptografickych hashovacich funkci, pokud by byl zajem :)
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

S prepisovaním C# do F# máš v podstate pravdu, ešte som len v polke knihy, tak používam veci, čo si pamätám z Haskellu spojené s C# :)
Paulos
stálý přispěvatel
stálý přispěvatel
Příspěvky: 439
Registrován: úte čer 17, 2008 17:06
Zařízení: Nokia Lumia 925, 32 GB
Kontaktovat uživatele:

Code Kata: staňte sa lepším programátorom

Příspěvek od Paulos »

Můžu zveřejnit svoje, ale někdo se tady asi mírně zasměje :-D (nebo taky možná ne, já jsem pověstný magickými čísly)

Kód: Vybrat vše

public static int Add(string numbers)
        {
            if (string.IsNullOrEmpty(numbers))
                return 0;

            int resultNum = 0;
            List<int> negativeNumbers = new List<int>();

            char[] delimiter = new char[] {',', '\n'};
            if (numbers.StartsWith("//"))
            {
                delimiter[0] = numbers[2];
                numbers = numbers.Substring(numbers.IndexOf('\n') + 1);
            }

            foreach(string strNumber in numbers.Split(delimiter))
            {
                int currentNum = 0;
                if ((currentNum = int.Parse(strNumber)) < 0)
                {
                    negativeNumbers.Add(currentNum);
                    continue;
                }
                resultNum += currentNum;
            }

            if(negativeNumbers.Any())
                throw new ArgumentOutOfRangeException("These numbers entered are negative: " + string.Join(", ", negativeNumbers));

            return resultNum;
        }
Jen by mě zajímalo, který z těch dvou přístupů je v praxi efektivnější a lepší: kontrolovat číslo, zda je menší okamžitě při parsování, nebo druhý cyklus, který vybere ta záporná čísla?
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Jen by mě zajímalo, který z těch dvou přístupů je v praxi efektivnější a lepší: kontrolovat číslo, zda je menší okamžitě při parsování, nebo druhý cyklus, který vybere ta záporná čísla?
Záleží, čo myslíš pod lepší. Pre mňa je "lepší" zápis

Kód: Vybrat vše

 var negatives = numbers.Where(l=> l < 0);
 if (negatives.Any()) ...
pretože je čitateľnejší, pri prvom pohľade viem, čo vyjadruje
Paulos
stálý přispěvatel
stálý přispěvatel
Příspěvky: 439
Registrován: úte čer 17, 2008 17:06
Zařízení: Nokia Lumia 925, 32 GB
Kontaktovat uživatele:

Code Kata: staňte sa lepším programátorom

Příspěvek od Paulos »

Jj, každého názor, ale tady máš asi pravdu. Moje řešení je zbytečně složité. :)
Tigerish
nováček
nováček
Příspěvky: 34
Registrován: stř lis 09, 2011 17:20
Zařízení: Samsung Omnia 7

Code Kata: staňte sa lepším programátorom

Příspěvek od Tigerish »

Tak sem to taky zkusil. A smutne musim konstatovat, ze bude asi vhodne se trosku venovat Linq :) Coz je asi smysl techto cviceni. Ale fakt by nebylo spatne davat reseni chytrejch kluku az na zaver, treba po tydnu.

Kód: Vybrat vše

 
public class Calculator
{
    public int Add(string input)
    {
        if (String.IsNullOrEmpty(input))
            return 0;

        List<int> numbers;
        GetNumbers(input, out numbers);

        int sum = 0;
        List<int> negatives = new List<int>();
        foreach (int i in numbers)
        {
            if (i < 0)
                negatives.Add(i);
            else
                sum += i;
        }

        if (negatives.Count > 0)
        {
            throw new ArgumentException("Negatives not allowed " + String.Join(", ", negatives));
        }

        return sum;
    }

    private bool GetNumbers(string input, out List<int> numbers)
    {
        numbers = new List<int>();

        string[] chars;

        //vyber oddelovacu
        if (input.StartsWith("//"))
        {
            string delimiter = input.Substring(2, input.IndexOf('\n') - 2);
            chars = new string[] { delimiter, "\n" };
        }
        else
        {
            chars = new string[] { ",", "\n"};
        }   

        //oddeleni znaku
        string[] sNumbers = input.Split(chars, StringSplitOptions.None);

        //parsovani cisel
        int number;
        bool isOK = true;
        for(int i = sNumbers[0].StartsWith("//") ? 1 : 0; i < sNumbers.Length; i++)
        {
            //hodnoceni validniho vstupu
            if (int.TryParse(sNumbers[i], out number))
                numbers.Add(number);
            else
            {
                isOK = false;
            }
        }

        return isOK;
    }
}
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Zmysel určite nie je LINQ, aj keď podľa mňa je LINQ najlepšia vec na .NETe oproti iným platformám. Zmyslom je zlepšiť sa v programovaní, čo môže znamenať napríklad naučiť sa LINQ.
Tigerish
nováček
nováček
Příspěvky: 34
Registrován: stř lis 09, 2011 17:20
Zařízení: Samsung Omnia 7

Code Kata: staňte sa lepším programátorom

Příspěvek od Tigerish »

jo tak to bylo mysleno :)
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Tak dáme si nejakú ďalšiu Katu? Svoje riešenie postnem až po týždni :)
Paulos
stálý přispěvatel
stálý přispěvatel
Příspěvky: 439
Registrován: úte čer 17, 2008 17:06
Zařízení: Nokia Lumia 925, 32 GB
Kontaktovat uživatele:

Code Kata: staňte sa lepším programátorom

Příspěvek od Paulos »

Jasná věc :-)
Martin Suchan
smartmaniak
smartmaniak
Příspěvky: 1138
Registrován: pát bře 11, 2011 10:48
Zařízení: Nokia Lumia 925
Bydliště: Praha

Code Kata: staňte sa lepším programátorom

Příspěvek od Martin Suchan »

nejlepe reseni nekde shromazdovat a postnout az najednou... jako cviceni na matfyzu 8-)
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Nová Kata:

The file football.dat contains the results from the English Premier League for 2001/2. The columns labeled ‘F’ and ‘A’ contain the total number of goals scored for and against each team in that season (so Arsenal scored 79 goals against opponents, and had 36 goals scored against them). Write a program to print the name of the team with the smallest difference in ‘for’ and ‘against’ goals.

To, že ten súbor obsahuje okrem dát aj nejaké nezmysly (link, 2 html značky) nie je chýba, ale výzva :)
Igor Kulman
častý přispěvatel
častý přispěvatel
Příspěvky: 228
Registrován: stř bře 28, 2012 12:46
Zařízení: ano

Code Kata: staňte sa lepším programátorom

Příspěvek od Igor Kulman »

Necroman píše:nejlepe reseni nekde shromazdovat a postnout az najednou... jako cviceni na matfyzu 8-)
To je dobrý nápad, dohodnime sa, že svoje riešenia budeme zverejňovať vždy týždeň po zadaní.

Pre aktuálnu Katu (parsovanie tabuľky z futbalu) svoje riešenia postnite sem v štvrtok 9.8.2012
Paulos
stálý přispěvatel
stálý přispěvatel
Příspěvky: 439
Registrován: úte čer 17, 2008 17:06
Zařízení: Nokia Lumia 925, 32 GB
Kontaktovat uživatele:

Code Kata: staňte sa lepším programátorom

Příspěvek od Paulos »

Igor Kulman píše:To, že ten súbor obsahuje okrem dát aj nejaké nezmysly (link, 2 html značky) nie je chýba, ale výzva :)
Já už myslel, že budu parsovat nesmysly v datech, a ono je to takhle pěkně oddělené. :)
Odpovědět

Zpět na „Programování a vývoj“

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 41 hostů