trackler 2.0.5.8 → 2.0.5.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a0e02be1736f9ad6f815b3593e22e0338b90bb5
4
- data.tar.gz: f6a8a9b2ee6b9afaa21cee8f4fdce3b2962b6db4
3
+ metadata.gz: d1f9e78737566c55c139024513a73f38029f2a0c
4
+ data.tar.gz: 853360aad86762df2a9279f3ad209e4497c739ad
5
5
  SHA512:
6
- metadata.gz: cab4b14cee19781307d566eed637b27a43e1dd980f9227881a1b9c066bee293ebabd741850259e437d3c42248bbc758ef97daadb4275cfe7e105c4e751a1b609
7
- data.tar.gz: 9ccafd1cfc519b3903983fa6e291ca8f0f77afbc2be851144e8edc12416f3280b74e983e501d5beb93d7b63d5d84fafe70480f91a44031e9783c04df26e92762
6
+ metadata.gz: 1517522938b3420f81dd931fb53458a99858c61e4673ec0413c120fc9aff827306e257fb5a316a21a2b771c12ae8a859ea943b53967ade8471031c9761e139e6
7
+ data.tar.gz: 527684182f9afe7b3e1e4a8b9fbc0a07e1a60dc0272d1188efb311678f065d4eb49118f5c059a87bb6d8a6daf0158a20e06dea9d45c69c746b01effb5541c3ed
@@ -3,5 +3,5 @@ multiples of either 3 or 5, we get 3, 5, 6 and 9, 10, 12, 15, and 18.
3
3
 
4
4
  The sum of these multiples is 78.
5
5
 
6
- Write a program that can find the sum of the multiples of a given set of
7
- numbers.
6
+ Write a program that, given a number, can find the sum of the multiples
7
+ of a given set of numbers, up to but not including that number.
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.5.8"
2
+ VERSION = "2.0.5.9"
3
3
  end
@@ -560,6 +560,15 @@
560
560
  "Transforming"
561
561
  ]
562
562
  },
563
+ {
564
+ "slug": "markdown",
565
+ "difficulty": 5,
566
+ "topics": [
567
+ "Parsing",
568
+ "Transforming",
569
+ "Refactoring"
570
+ ]
571
+ },
563
572
  {
564
573
  "slug": "run-length-encoding",
565
574
  "difficulty": 5,
@@ -568,6 +577,13 @@
568
577
  "Transforming"
569
578
  ]
570
579
  },
580
+ {
581
+ "slug": "book-store",
582
+ "difficulty": 5,
583
+ "topics": [
584
+ "Recursion"
585
+ ]
586
+ },
571
587
  {
572
588
  "slug": "tournament",
573
589
  "difficulty": 6,
@@ -706,6 +722,14 @@
706
722
  "Logic"
707
723
  ]
708
724
  },
725
+ {
726
+ "slug": "connect",
727
+ "difficulty": 8,
728
+ "topics": [
729
+ "Parsing",
730
+ "Transforming"
731
+ ]
732
+ },
709
733
  {
710
734
  "slug": "say",
711
735
  "difficulty": 8,
@@ -0,0 +1,95 @@
1
+ using System.Collections.Generic;
2
+ using System.Linq;
3
+ using NUnit.Framework;
4
+
5
+ [TestFixture]
6
+ public class BookStoreTest
7
+ {
8
+ [Test]
9
+ public void Basket_with_single_book()
10
+ {
11
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1)), Is.EqualTo(8));
12
+ }
13
+
14
+ [Ignore("Remove to run test")]
15
+ [Test]
16
+ public void Basket_with_two_of_same_book()
17
+ {
18
+ Assert.That(BookStore.CalculateTotalCost(MakeList(2, 2)), Is.EqualTo(16));
19
+ }
20
+
21
+ [Ignore("Remove to run test")]
22
+ [Test]
23
+ public void Empty_basket()
24
+ {
25
+ Assert.That(BookStore.CalculateTotalCost(MakeList()), Is.EqualTo(0));
26
+ }
27
+
28
+ [Ignore("Remove to run test")]
29
+ [Test]
30
+ public void Basket_with_two_different_books()
31
+ {
32
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 2)), Is.EqualTo(15.2));
33
+ }
34
+
35
+ [Ignore("Remove to run test")]
36
+ [Test]
37
+ public void Basket_with_three_different_books()
38
+ {
39
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 2, 3)), Is.EqualTo(21.6));
40
+ }
41
+
42
+ [Ignore("Remove to run test")]
43
+ [Test]
44
+ public void Basket_with_four_different_books()
45
+ {
46
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 2, 3, 4)), Is.EqualTo(25.6));
47
+ }
48
+
49
+ [Ignore("Remove to run test")]
50
+ [Test]
51
+ public void Basket_with_five_different_books()
52
+ {
53
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 2, 3, 4, 5)), Is.EqualTo(30));
54
+ }
55
+
56
+ [Ignore("Remove to run test")]
57
+ [Test]
58
+ public void Basket_with_eight_books()
59
+ {
60
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 5)), Is.EqualTo(51.20));
61
+ }
62
+
63
+ [Ignore("Remove to run test")]
64
+ [Test]
65
+ public void Basket_with_nine_books()
66
+ {
67
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5)), Is.EqualTo(55.60));
68
+ }
69
+
70
+ [Ignore("Remove to run test")]
71
+ [Test]
72
+ public void Basket_with_ten_books()
73
+ {
74
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5)), Is.EqualTo(60));
75
+ }
76
+
77
+ [Ignore("Remove to run test")]
78
+ [Test]
79
+ public void Basket_with_eleven_books()
80
+ {
81
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1)), Is.EqualTo(68));
82
+ }
83
+
84
+ [Ignore("Remove to run test")]
85
+ [Test]
86
+ public void Basket_with_twelve_books()
87
+ {
88
+ Assert.That(BookStore.CalculateTotalCost(MakeList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 2)), Is.EqualTo(75.20));
89
+ }
90
+
91
+ private static List<int> MakeList(params int[] values)
92
+ {
93
+ return values.ToList();
94
+ }
95
+ }
@@ -0,0 +1,70 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Linq;
4
+
5
+ public class BookStore
6
+ {
7
+ public static double CalculateTotalCost(List<int> books)
8
+ {
9
+ return CalculateTotalCost(books, 0);
10
+ }
11
+
12
+ private static double CalculateTotalCost(List<int> books, double priceSoFar)
13
+ {
14
+ if (books.Count == 0)
15
+ {
16
+ return priceSoFar;
17
+ }
18
+
19
+ var groups = books
20
+ .GroupBy(b => b)
21
+ .Select(g => g.Key)
22
+ .ToList();
23
+
24
+ var minPrice = double.MaxValue;
25
+
26
+ for (int i = groups.Count; i >= 1; i--)
27
+ {
28
+ var itemsToRemove = groups.Take(i).ToList();
29
+ var remaining = books.ToList();
30
+
31
+ foreach (var item in itemsToRemove)
32
+ {
33
+ remaining.Remove(item);
34
+ }
35
+
36
+ var price = CalculateTotalCost(remaining.ToList(), priceSoFar + CostPerGroup(i));
37
+ minPrice = Math.Min(minPrice, price);
38
+ }
39
+
40
+ return minPrice;
41
+ }
42
+
43
+ private static double CostPerGroup(int groupSize)
44
+ {
45
+ double discountPercentage;
46
+
47
+ switch (groupSize)
48
+ {
49
+ case 1:
50
+ discountPercentage = 0;
51
+ break;
52
+ case 2:
53
+ discountPercentage = 5;
54
+ break;
55
+ case 3:
56
+ discountPercentage = 10;
57
+ break;
58
+ case 4:
59
+ discountPercentage = 20;
60
+ break;
61
+ case 5:
62
+ discountPercentage = 25;
63
+ break;
64
+ default:
65
+ throw new InvalidOperationException($"Invalid group size: {groupSize}");
66
+ }
67
+
68
+ return 8 * groupSize * (100 - discountPercentage) / 100;
69
+ }
70
+ }
@@ -0,0 +1,131 @@
1
+ using NUnit.Framework;
2
+ using System.Linq;
3
+
4
+ public class ConnectTest
5
+ {
6
+ private static string MakeBoard(string[] board)
7
+ {
8
+ return string.Join("\n", board.Select(x => x.Replace(" ", "")));
9
+ }
10
+
11
+ [Test]
12
+ public void Empty_board_has_no_winner()
13
+ {
14
+ var lines = new[]
15
+ {
16
+ ". . . . . ",
17
+ " . . . . . ",
18
+ " . . . . . ",
19
+ " . . . . . ",
20
+ " . . . . ."
21
+ };
22
+ var board = new Connect(MakeBoard(lines));
23
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.None));
24
+ }
25
+
26
+ [Ignore("Remove to run test")]
27
+ [Test]
28
+ public void One_by_one_board_with_black_stone()
29
+ {
30
+ var lines = new[] { "X" };
31
+ var board = new Connect(MakeBoard(lines));
32
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.Black));
33
+ }
34
+
35
+ [Ignore("Remove to run test")]
36
+ [Test]
37
+ public void One_by_one_board_with_white_stone()
38
+ {
39
+ var lines = new[] { "O" };
40
+ var board = new Connect(MakeBoard(lines));
41
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.White));
42
+ }
43
+
44
+ [Ignore("Remove to run test")]
45
+ [Test]
46
+ public void Convoluted_path()
47
+ {
48
+ var lines = new[]
49
+ {
50
+ ". X X . . ",
51
+ " X . X . X ",
52
+ " . X . X . ",
53
+ " . X X . . ",
54
+ " O O O O O"
55
+ };
56
+ var board = new Connect(MakeBoard(lines));
57
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.Black));
58
+ }
59
+
60
+ [Ignore("Remove to run test")]
61
+ [Test]
62
+ public void Rectangle_black_wins()
63
+ {
64
+ var lines = new[]
65
+ {
66
+ ". O . . ",
67
+ " O X X X ",
68
+ " O X O . ",
69
+ " X X O X ",
70
+ " . O X ."
71
+ };
72
+ var board = new Connect(MakeBoard(lines));
73
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.Black));
74
+ }
75
+
76
+ [Ignore("Remove to run test")]
77
+ [Test]
78
+ public void Rectangle_white_wins()
79
+ {
80
+ var lines = new[]
81
+ {
82
+ ". O . . ",
83
+ " O X X X ",
84
+ " O O O . ",
85
+ " X X O X ",
86
+ " . O X ."
87
+ };
88
+ var board = new Connect(MakeBoard(lines));
89
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.White));
90
+ }
91
+
92
+ [Ignore("Remove to run test")]
93
+ [Test]
94
+ public void Spiral_black_wins()
95
+ {
96
+ var lines = new[]
97
+ {
98
+ "OXXXXXXXX",
99
+ "OXOOOOOOO",
100
+ "OXOXXXXXO",
101
+ "OXOXOOOXO",
102
+ "OXOXXXOXO",
103
+ "OXOOOXOXO",
104
+ "OXXXXXOXO",
105
+ "OOOOOOOXO",
106
+ "XXXXXXXXO"
107
+ };
108
+ var board = new Connect(MakeBoard(lines));
109
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.Black));
110
+ }
111
+
112
+ [Ignore("Remove to run test")]
113
+ [Test]
114
+ public void Spiral_nobody_wins()
115
+ {
116
+ var lines = new[]
117
+ {
118
+ "OXXXXXXXX",
119
+ "OXOOOOOOO",
120
+ "OXOXXXXXO",
121
+ "OXOXOOOXO",
122
+ "OXOX.XOXO",
123
+ "OXOOOXOXO",
124
+ "OXXXXXOXO",
125
+ "OOOOOOOXO",
126
+ "XXXXXXXXO"
127
+ };
128
+ var board = new Connect(MakeBoard(lines));
129
+ Assert.That(board.Result(), Is.EqualTo(Connect.Winner.None));
130
+ }
131
+ }
@@ -0,0 +1,121 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Drawing;
4
+ using System.Linq;
5
+
6
+ public class Connect
7
+ {
8
+ public enum Winner
9
+ {
10
+ White,
11
+ Black,
12
+ None
13
+ }
14
+
15
+ public enum Cell
16
+ {
17
+ Empty,
18
+ White,
19
+ Black
20
+ }
21
+
22
+ private readonly Cell[][] board;
23
+
24
+ public Connect(string input)
25
+ {
26
+ board = ParseBoard(input);
27
+ }
28
+
29
+ private static Cell CharToCell(char c)
30
+ {
31
+ switch (c)
32
+ {
33
+ case 'O': return Cell.White;
34
+ case 'X': return Cell.Black;
35
+ default: return Cell.Empty;
36
+ }
37
+ }
38
+
39
+ private static Cell[][] ParseBoard(string input)
40
+ {
41
+ var split = input.Split('\n');
42
+ var rows = split.Length;
43
+ var cols = split[0].Length;
44
+
45
+ return split.Select(row => row.Select(CharToCell).ToArray()).ToArray();
46
+ }
47
+
48
+ private int Cols => board[0].Length;
49
+ private int Rows => board.Length;
50
+
51
+ private bool IsValidCoordinate(Point coordinate) =>
52
+ coordinate.Y >= 0 && coordinate.Y < Rows &&
53
+ coordinate.X >= 0 && coordinate.X < Cols;
54
+
55
+ private bool CellAtCoordinateEquals(Cell cell, Point coordinate) => board[coordinate.Y][coordinate.X] == cell;
56
+
57
+ private HashSet<Point> Adjacent(Cell cell, Point coordinate)
58
+ {
59
+ var row = coordinate.Y;
60
+ var col = coordinate.X;
61
+
62
+ var coords = new[]
63
+ {
64
+ new Point(col + 1, row - 1),
65
+ new Point(col, row - 1),
66
+ new Point(col - 1, row ),
67
+ new Point(col + 1, row ),
68
+ new Point(col - 1, row + 1),
69
+ new Point(col, row + 1)
70
+ };
71
+
72
+ return new HashSet<Point>(coords.Where(coord => IsValidCoordinate(coord) && CellAtCoordinateEquals(cell, coord)));
73
+ }
74
+
75
+ private bool ValidPath(Cell cell, Func<Cell[][], Point, bool> stop, HashSet<Point> processed, Point coordinate)
76
+ {
77
+ if (stop(board, coordinate))
78
+ return true;
79
+
80
+ var next = Adjacent(cell, coordinate);
81
+ next.ExceptWith(processed);
82
+
83
+ if (!next.Any())
84
+ return false;
85
+
86
+ return next.Any(nextCoord => {
87
+ var updatedProcessed = new HashSet<Point>(processed);
88
+ updatedProcessed.Add(nextCoord);
89
+
90
+ return ValidPath(cell, stop, updatedProcessed, nextCoord);
91
+ });
92
+ }
93
+
94
+ private bool IsWhiteStop(Cell[][] board, Point coordinate) => coordinate.Y == Rows - 1;
95
+ private bool IsBlackStop(Cell[][] board, Point coordinate) => coordinate.X == Cols - 1;
96
+
97
+ private HashSet<Point> WhiteStart() =>
98
+ new HashSet<Point>(Enumerable.Range(0, Cols).Select(col => new Point(col, 0)).Where(coord => CellAtCoordinateEquals(Cell.White, coord)));
99
+
100
+ private HashSet<Point> BlackStart() =>
101
+ new HashSet<Point>(Enumerable.Range(0, Rows).Select(row => new Point(0, row)).Where(coord => CellAtCoordinateEquals(Cell.Black, coord)));
102
+
103
+ private bool ColorWins(Cell cell, Func<Cell[][], Point, bool> stop, Func<HashSet<Point>> start)
104
+ {
105
+ return start().Any(coordinate => ValidPath(cell, stop, new HashSet<Point>(), coordinate));
106
+ }
107
+
108
+ private bool WhiteWins() => ColorWins(Cell.White, IsWhiteStop, WhiteStart);
109
+ private bool BlackWins() => ColorWins(Cell.Black, IsBlackStop, BlackStart);
110
+
111
+ public Winner Result()
112
+ {
113
+ if (WhiteWins())
114
+ return Winner.White;
115
+
116
+ if (BlackWins())
117
+ return Winner.Black;
118
+
119
+ return Winner.None;
120
+ }
121
+ }
@@ -38,7 +38,7 @@
38
38
  <Reference Include="Microsoft.CSharp" />
39
39
  </ItemGroup>
40
40
  <ItemGroup>
41
- <Compile Include="**\*.cs" Exclude="sgf-parsing\SgfParsing.cs" />
41
+ <Compile Include="**\*.cs" Exclude="sgf-parsing\SgfParsing.cs;markdown\Markdown.cs" />
42
42
  </ItemGroup>
43
43
  <ItemGroup>
44
44
  <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
@@ -0,0 +1,108 @@
1
+ using System;
2
+ using System.Linq;
3
+ using System.Text.RegularExpressions;
4
+
5
+ public static class Markdown
6
+ {
7
+ private static string OpeningTag(string tag) => $"<{tag}>";
8
+ private static string ClosingTag(string tag) => $"</{tag}>";
9
+ private static string WrapInTag(this string text, string tag) => $"{OpeningTag(tag)}{text}{ClosingTag(tag)}";
10
+ private static bool StartsWithTag(this string text, string tag) => text.StartsWith(OpeningTag(tag));
11
+
12
+ private const string HeaderMarkdown = "#";
13
+ private const string BoldMarkdown = "__";
14
+ private const string ItalicMarkdown = "_";
15
+ private const string ListItemMarkdown = "*";
16
+
17
+ private const string BoldTag = "em";
18
+ private const string ItalicTag = "i";
19
+ private const string ParagraphTag = "p";
20
+ private const string ListTag = "ul";
21
+ private const string ListItemTag = "li";
22
+
23
+ private static string ParseDelimited(this string markdown, string delimiter, string tag)
24
+ {
25
+ var pattern = $"{delimiter}(.+){delimiter}";
26
+ var replacement = "$1".WrapInTag(tag);
27
+ return Regex.Replace(markdown, pattern, replacement);
28
+ }
29
+
30
+ private static string ParseBold(this string markdown) => markdown.ParseDelimited(BoldMarkdown, BoldTag);
31
+ private static string ParseItalic(this string markdown) => markdown.ParseDelimited(ItalicMarkdown, ItalicTag);
32
+
33
+ private static string ParseText(this string markdown, bool list)
34
+ {
35
+ var textHtml = markdown
36
+ .ParseBold()
37
+ .ParseItalic();
38
+
39
+ return list ? textHtml : textHtml.WrapInTag(ParagraphTag);
40
+ }
41
+
42
+ private static Tuple<bool, string> ParseHeader(this string markdown, bool list)
43
+ {
44
+ var headerNumber =
45
+ markdown
46
+ .TakeWhile(c => c == HeaderMarkdown[0])
47
+ .Count();
48
+
49
+ if (headerNumber == 0)
50
+ return null;
51
+
52
+ var headerTag = $"h{headerNumber}";
53
+ var headerHtml = markdown.Substring(headerNumber + 1).WrapInTag(headerTag);
54
+ var html = list ? ClosingTag(ListTag) + headerHtml : headerHtml;
55
+
56
+ return Tuple.Create(false, html);
57
+ }
58
+
59
+ private static Tuple<bool, string> ParseLineItem(this string markdown, bool list)
60
+ {
61
+ if (!markdown.StartsWith(ListItemMarkdown))
62
+ return null;
63
+
64
+ var innerHtml =
65
+ markdown
66
+ .Substring(2)
67
+ .ParseText(true)
68
+ .WrapInTag(ListItemTag);
69
+
70
+ var html = list ? innerHtml : OpeningTag(ListTag) + innerHtml;
71
+ return Tuple.Create(true, html);
72
+ }
73
+
74
+ private static Tuple<bool, string> ParseParagraph(this string markdown, bool list)
75
+ {
76
+ if (list)
77
+ return Tuple.Create(false, ClosingTag(ListTag) + markdown.ParseText(list));
78
+
79
+ return Tuple.Create(false, markdown.ParseText(list));
80
+ }
81
+
82
+ private static Tuple<bool, string> ParseLine(Tuple<bool, string> accumulator, string markdown)
83
+ {
84
+ var list = accumulator.Item1;
85
+ var html = accumulator.Item2;
86
+
87
+ var result =
88
+ markdown.ParseHeader(list) ??
89
+ markdown.ParseLineItem(list) ??
90
+ markdown.ParseParagraph(list);
91
+
92
+ if (result == null)
93
+ throw new ArgumentException("Invalid markdown");
94
+
95
+ return Tuple.Create(result.Item1, html + result.Item2);
96
+ }
97
+
98
+ public static string Parse(string markdown)
99
+ {
100
+ var lines = markdown.Split('\n');
101
+ var result = lines.Aggregate(Tuple.Create(false, ""), ParseLine);
102
+
103
+ var list = result.Item1;
104
+ var html = result.Item2;
105
+
106
+ return list ? html + ClosingTag(ListTag) : html;
107
+ }
108
+ }
@@ -0,0 +1,3 @@
1
+ ## Hints
2
+ For this exercise the following C# feature comes in handy:
3
+ - [String Interpolation](https://msdn.microsoft.com/en-us/library/dn961160.aspx) (C# 6 and up).
@@ -0,0 +1,151 @@
1
+ using System;
2
+ using System.Text.RegularExpressions;
3
+
4
+ public static class Markdown
5
+ {
6
+ private static string Wrap(string text, string tag) => "<" + tag + ">" + text + "</" + tag + ">";
7
+
8
+ private static bool IsTag(string text, string tag) => text.StartsWith("<" + tag + ">");
9
+
10
+ private static string Parse(string markdown, string delimiter, string tag)
11
+ {
12
+ var pattern = delimiter + "(.+)" + delimiter;
13
+ var replacement = "<" + tag + ">$1</" + tag + ">";
14
+ return Regex.Replace(markdown, pattern, replacement);
15
+ }
16
+
17
+ private static string Parse__(string markdown) => Parse(markdown, "__", "em");
18
+
19
+ private static string Parse_(string markdown) => Parse(markdown, "_", "i");
20
+
21
+ private static string ParseText(string markdown, bool list)
22
+ {
23
+ var parsedText = Parse_(Parse__((markdown)));
24
+
25
+ if (list)
26
+ {
27
+ return parsedText;
28
+ }
29
+ else
30
+ {
31
+ return Wrap(parsedText, "p");
32
+ }
33
+ }
34
+
35
+ private static string ParseHeader(string markdown, bool list, out bool inListAfter)
36
+ {
37
+ var count = 0;
38
+
39
+ for (int i = 0; i < markdown.Length; i++)
40
+ {
41
+ if (markdown[i] == '#')
42
+ {
43
+ count += 1;
44
+ }
45
+ else
46
+ {
47
+ break;
48
+ }
49
+ }
50
+
51
+ if (count == 0)
52
+ {
53
+ inListAfter = list;
54
+ return null;
55
+ }
56
+
57
+ var headerTag = "h" + count;
58
+ var headerHtml = Wrap(markdown.Substring(count + 1), headerTag);
59
+
60
+ if (list)
61
+ {
62
+ inListAfter = false;
63
+ return "</ul>" + headerHtml;
64
+ }
65
+ else
66
+ {
67
+ inListAfter = false;
68
+ return headerHtml;
69
+ }
70
+ }
71
+
72
+ private static string ParseLineItem(string markdown, bool list, out bool inListAfter)
73
+ {
74
+ if (markdown.StartsWith("*"))
75
+ {
76
+ var innerHtml = Wrap(ParseText(markdown.Substring(2), true), "li");
77
+
78
+ if (list)
79
+ {
80
+ inListAfter = true;
81
+ return innerHtml;
82
+ }
83
+ else
84
+ {
85
+ inListAfter = true;
86
+ return "<ul>" + innerHtml;
87
+ }
88
+ }
89
+
90
+ inListAfter = list;
91
+ return null;
92
+ }
93
+
94
+ private static string ParseParagraph(string markdown, bool list, out bool inListAfter)
95
+ {
96
+ if (!list)
97
+ {
98
+ inListAfter = false;
99
+ return ParseText(markdown, list);
100
+ }
101
+ else
102
+ {
103
+ inListAfter = false;
104
+ return "</ul>" + ParseText(markdown, list);
105
+ }
106
+ }
107
+
108
+ private static string ParseLine(string markdown, bool list, out bool inListAfter)
109
+ {
110
+ var result = ParseHeader(markdown, list, out inListAfter);
111
+
112
+ if (result == null)
113
+ {
114
+ result = ParseLineItem(markdown, list, out inListAfter);
115
+ }
116
+
117
+ if (result == null)
118
+ {
119
+ result = ParseParagraph(markdown, list, out inListAfter);
120
+ }
121
+
122
+ if (result == null)
123
+ {
124
+ throw new ArgumentException("Invalid markdown");
125
+ }
126
+
127
+ return result;
128
+ }
129
+
130
+ public static string Parse(string markdown)
131
+ {
132
+ var lines = markdown.Split('\n');
133
+ var result = "";
134
+ var list = false;
135
+
136
+ for (int i = 0; i < lines.Length; i++)
137
+ {
138
+ var lineResult = ParseLine(lines[i], list, out list);
139
+ result += lineResult;
140
+ }
141
+
142
+ if (list)
143
+ {
144
+ return result + "</ul>";
145
+ }
146
+ else
147
+ {
148
+ return result;
149
+ }
150
+ }
151
+ }
@@ -0,0 +1,76 @@
1
+ using NUnit.Framework;
2
+
3
+ public class MarkdownTest
4
+ {
5
+ [Test]
6
+ public void Parses_normal_text_as_a_paragraph()
7
+ {
8
+ var input = "This will be a paragraph";
9
+ var expected = "<p>This will be a paragraph</p>";
10
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
11
+ }
12
+
13
+ [Test]
14
+ public void Parsing_italics()
15
+ {
16
+ var input = "_This will be italic_";
17
+ var expected = "<p><i>This will be italic</i></p>";
18
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
19
+ }
20
+
21
+ [Test]
22
+ public void Parsing_bold_text()
23
+ {
24
+ var input = "__This will be bold__";
25
+ var expected = "<p><em>This will be bold</em></p>";
26
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
27
+ }
28
+
29
+ [Test]
30
+ public void Mixed_normal_italics_and_bold_text()
31
+ {
32
+ var input = "This will _be_ __mixed__";
33
+ var expected = "<p>This will <i>be</i> <em>mixed</em></p>";
34
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
35
+ }
36
+
37
+ [Test]
38
+ public void With_h1_header_level()
39
+ {
40
+ var input = "# This will be an h1";
41
+ var expected = "<h1>This will be an h1</h1>";
42
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
43
+ }
44
+
45
+ [Test]
46
+ public void With_h2_header_level()
47
+ {
48
+ var input = "## This will be an h2";
49
+ var expected = "<h2>This will be an h2</h2>";
50
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
51
+ }
52
+
53
+ [Test]
54
+ public void With_h6_header_level()
55
+ {
56
+ var input = "###### This will be an h6";
57
+ var expected = "<h6>This will be an h6</h6>";
58
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
59
+ }
60
+
61
+ [Test]
62
+ public void Unordered_lists()
63
+ {
64
+ var input = "* Item 1\n* Item 2";
65
+ var expected = "<ul><li>Item 1</li><li>Item 2</li></ul>";
66
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
67
+ }
68
+
69
+ [Test]
70
+ public void With_a_little_bit_of_everything()
71
+ {
72
+ var input = "# Header!\n* __Bold Item__\n* _Italic Item_";
73
+ var expected = "<h1>Header!</h1><ul><li><em>Bold Item</em></li><li><i>Italic Item</i></li></ul>";
74
+ Assert.That(Markdown.Parse(input), Is.EqualTo(expected));
75
+ }
76
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trackler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.5.8
4
+ version: 2.0.5.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Owen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-23 00:00:00.000000000 Z
11
+ date: 2016-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -1298,6 +1298,8 @@ files:
1298
1298
  - tracks/csharp/exercises/binary-search/Example.cs
1299
1299
  - tracks/csharp/exercises/bob/BobTest.cs
1300
1300
  - tracks/csharp/exercises/bob/Example.cs
1301
+ - tracks/csharp/exercises/book-store/BookStoreTest.cs
1302
+ - tracks/csharp/exercises/book-store/Example.cs
1301
1303
  - tracks/csharp/exercises/bowling/BowlingTest.cs
1302
1304
  - tracks/csharp/exercises/bowling/Example.cs
1303
1305
  - tracks/csharp/exercises/bracket-push/BracketPushTest.cs
@@ -1308,6 +1310,8 @@ files:
1308
1310
  - tracks/csharp/exercises/circular-buffer/Example.cs
1309
1311
  - tracks/csharp/exercises/clock/ClockTest.cs
1310
1312
  - tracks/csharp/exercises/clock/Example.cs
1313
+ - tracks/csharp/exercises/connect/ConnectTest.cs
1314
+ - tracks/csharp/exercises/connect/Example.cs
1311
1315
  - tracks/csharp/exercises/crypto-square/CryptoSquareTest.cs
1312
1316
  - tracks/csharp/exercises/crypto-square/Example.cs
1313
1317
  - tracks/csharp/exercises/custom-set/CustomSetTest.cs
@@ -1356,6 +1360,10 @@ files:
1356
1360
  - tracks/csharp/exercises/list-ops/ListOpsTest.cs
1357
1361
  - tracks/csharp/exercises/luhn/Example.cs
1358
1362
  - tracks/csharp/exercises/luhn/LuhnTest.cs
1363
+ - tracks/csharp/exercises/markdown/Example.cs
1364
+ - tracks/csharp/exercises/markdown/HINTS.md
1365
+ - tracks/csharp/exercises/markdown/Markdown.cs
1366
+ - tracks/csharp/exercises/markdown/MarkdownTest.cs
1359
1367
  - tracks/csharp/exercises/matrix/Example.cs
1360
1368
  - tracks/csharp/exercises/matrix/MatrixTest.cs
1361
1369
  - tracks/csharp/exercises/meetup/Example.cs