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

Vše okolo vývoje aplikací pro platformy Windows Phone a Windows 10 Mobile
Uživatelský avatar
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 » pon črc 30, 2012 8:10

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.

Uživatelský avatar
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 » pon črc 30, 2012 8:42

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;

Uživatelský avatar
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 » pon črc 30, 2012 18:23

Na to, že sa tu na fóre každý hrá na wp7 programátora, tu asi ozajstných programátorov veľa nebude :)

Uživatelský avatar
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 » stř srp 01, 2012 10:01

Vážne sa nenájde nikto, kto by zverejnil svoje riešenie? Zaujíma ma, akým štýlom programujete.

Uživatelský avatar
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 » stř srp 01, 2012 10:22

Mel jsi to svoje zverejnit az po tydnu, takhle se kazdy kouknul na vysledek a dal uz ho to nemotivovalo :)

Uživatelský avatar
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 » stř srp 01, 2012 10:34

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 :)

Uživatelský avatar
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 » stř srp 01, 2012 10:46

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 :)

Uživatelský avatar
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 » stř srp 01, 2012 11:15

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# :)

Uživatelský avatar
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 » stř srp 01, 2012 11:22

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?

Uživatelský avatar
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 » stř srp 01, 2012 11:42

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

Uživatelský avatar
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 » stř srp 01, 2012 11:45

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 » stř srp 01, 2012 12:32

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;
    }
}

Uživatelský avatar
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 » stř srp 01, 2012 13:04

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 » stř srp 01, 2012 13:11

jo tak to bylo mysleno :)

Uživatelský avatar
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 » stř srp 01, 2012 15:44

Tak dáme si nejakú ďalšiu Katu? Svoje riešenie postnem až po týždni :)

Uživatelský avatar
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 » stř srp 01, 2012 16:22

Jasná věc :-)

Uživatelský avatar
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 » stř srp 01, 2012 18:36

nejlepe reseni nekde shromazdovat a postnout az najednou... jako cviceni na matfyzu 8-)

Uživatelský avatar
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 » čtv srp 02, 2012 15:24

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 :)

Uživatelský avatar
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 » pát srp 03, 2012 8:49

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

Uživatelský avatar
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 » pát srp 03, 2012 9:23

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 5 hostů