Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################

/obj/Debug
/bin/Debug
/.vs
6 changes: 6 additions & 0 deletions App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
</configuration>
26 changes: 26 additions & 0 deletions ChangeCalculatorFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SWCashRegister
{
public static class ChangeCalculatorFactory
{
private static RandomChangeCalculator randomChangeCalculator = new RandomChangeCalculator();
private static MinimumChangeCalculator minimumChangeCalculator = new MinimumChangeCalculator();

public static IChangeCalculator GetChangeCalculator(int changeAmount)
{
if (changeAmount % 3 == 0)
{
return randomChangeCalculator;
}
else
{
return minimumChangeCalculator;
}
}
}
}
38 changes: 38 additions & 0 deletions Currency.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SWCashRegister
{
public class Currency
{
public static Currency Hundred { get; } = new Currency("hundred", "hundreds", 10000);
public static Currency Fifty { get; } = new Currency("fifty", "fifties", 5000);
public static Currency Twenty { get; } = new Currency("twenty", "twenties", 2000);
public static Currency Ten { get; } = new Currency("ten", "tens", 1000);
public static Currency Five { get; } = new Currency("five", "fives", 500);
public static Currency Dollar { get; } = new Currency("dollar", "dollars", 100);
public static Currency Quarter { get; } = new Currency("quarter", "quarters", 25);
public static Currency Dime { get; } = new Currency("dime", "dimes", 10);
public static Currency Nickel { get; } = new Currency("nickel", "nickels", 5);
public static Currency Penny { get; } = new Currency("penny", "pennies", 1);

public static IEnumerable<Currency> List()
{
return new[] { Hundred, Fifty, Twenty, Ten, Five, Dollar, Quarter, Dime, Nickel, Penny };
}

private Currency(string name, string plural, int value)
{
Name = name;
Plural = plural;
Value = value;
}

public string Name { get; private set; }
public string Plural { get; private set; }
public int Value { get; private set; }
}
}
10 changes: 10 additions & 0 deletions Files/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
2.12,3.00
1.97,2.00
3.33,5.00
5.00,3.33
3.33,5.00
1.97, 2.00
34, 50
3.330,5.000
32.45,42.4
this,that
13 changes: 13 additions & 0 deletions IChangeCalculator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SWCashRegister
{
public interface IChangeCalculator
{
IList<(Currency, int)> GetChange(int changeAmount);
}
}
28 changes: 28 additions & 0 deletions MinimumChangeCalculator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SWCashRegister
{
public class MinimumChangeCalculator : IChangeCalculator
{
public IList<(Currency, int)> GetChange(int changeAmount)
{
List<(Currency Currency, int Quantity)> change = new List<(Currency Currency, int Quantity)>();

foreach (var currency in Currency.List())
{
if (changeAmount >= currency.Value)
{
int quantity = changeAmount / currency.Value;
change.Add((Currency: currency, Quantity: quantity));
changeAmount -= currency.Value * quantity;
}
}

return change;
}
}
}
98 changes: 98 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;

namespace SWCashRegister
{
class Program
{
static void Main(string[] args)
{
string line;

if (!System.IO.File.Exists("input.txt"))
{
Console.WriteLine("Could not find file input.txt.");
return;
}

try
{
using (var input = new StreamReader("input.txt"))
using (var output = new StreamWriter("output.txt"))
{
while ((line = input.ReadLine()) != null)
{
if (!ValidateLine(line))
{
Console.WriteLine($"Found invalid value: {line}");
continue;
}

var values = line.Split(',');
int price = (int)(Convert.ToDecimal(values[0]) * 100);
int amountPaid = (int)(Convert.ToDecimal(values[1]) * 100);

if (amountPaid < price)
{
Console.WriteLine($"Insufficient funds: {line}");
continue;
}

int changeAmount = amountPaid - price;

IChangeCalculator calculator = ChangeCalculatorFactory.GetChangeCalculator(price);
output.WriteLine(PrintChange(calculator.GetChange(changeAmount)));
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
}

/// <summary>
/// Returns true if the line contains two decimal values, separated by a comma
/// </summary>
/// <param name="line"></param>
/// <returns>True if line is correctly formatted</returns>
public static bool ValidateLine(string line)
{
var regex = new Regex(@"^\d+\.\d{2}\,\d+\.\d{2}$");
return regex.IsMatch(line) ;
}

/// <summary>
/// Gets a text description of change quantities.
/// </summary>
/// <param name="change">A list mapping a currency to a quantity</param>
/// <returns>Description of change.</returns>
public static string PrintChange(IList<(Currency Currency, int Quantity)> change)
{
List<string> changeText = new List<string>();

var sortedChange = change
.GroupBy(x => x.Currency)
.Select(g => new {
Currency = g.Key,
Quantity = g.Sum(x => x.Quantity)
})
.OrderByDescending(x => x.Currency.Value);

foreach (var denomination in sortedChange)
{
changeText.Add($"{denomination.Quantity} {(denomination.Quantity == 1 ? denomination.Currency.Name : denomination.Currency.Plural)}");
}

return String.Join(",", changeText);
}
}
}
36 changes: 36 additions & 0 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SWCashRegister")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SWCashRegister")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("83c9c135-36e1-4d63-bb89-04367da7da25")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
28 changes: 28 additions & 0 deletions RandomChangeCalculator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SWCashRegister
{
public class RandomChangeCalculator : IChangeCalculator
{
public IList<(Currency, int)> GetChange(int changeAmount)
{
List<(Currency Currency, int Quantity)> change = new List<(Currency Currency, int Quantity)>();
Random random = new Random();

while (changeAmount > 0)
{
List<Currency> availableCurrencies = Currency.List().Where(x => x.Value <= changeAmount).ToList();
int index = random.Next(0, availableCurrencies.Count());
Currency currency = availableCurrencies[index];
change.Add((Currency: currency, Quantity: 1));
changeAmount -= currency.Value;
}

return change;
}
}
}
62 changes: 62 additions & 0 deletions SWCashRegister.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{83C9C135-36E1-4D63-BB89-04367DA7DA25}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>SWCashRegister</RootNamespace>
<AssemblyName>SWCashRegister</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ChangeCalculatorFactory.cs" />
<Compile Include="Currency.cs" />
<Compile Include="IChangeCalculator.cs" />
<Compile Include="MinimumChangeCalculator.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RandomChangeCalculator.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Files\input.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
25 changes: 25 additions & 0 deletions SWCashRegister.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2026
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SWCashRegister", "SWCashRegister.csproj", "{83C9C135-36E1-4D63-BB89-04367DA7DA25}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{83C9C135-36E1-4D63-BB89-04367DA7DA25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83C9C135-36E1-4D63-BB89-04367DA7DA25}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83C9C135-36E1-4D63-BB89-04367DA7DA25}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83C9C135-36E1-4D63-BB89-04367DA7DA25}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09B5569E-E268-4199-994A-FE759C731E19}
EndGlobalSection
EndGlobal