8 Replies - 586 Views - Last Post: 04 September 2018 - 05:48 AM

#1 astonecipher   User is offline

  • Senior Systems Engineer
  • member icon

Reputation: 2906
  • View blog
  • Posts: 11,328
  • Joined: 03-December 12

I got bored

Posted 31 August 2018 - 11:27 AM

using System;
using System.Collections.Generic;
using System.Reflection;

public class Program
{

	
	public static void Maths(int hourly)
	{
		int weekly = (hourly * 40);
		int monthly = (weekly * 4);
		int yearly = (hourly * 2080);
		
		Console.WriteLine("{0}{1}{2}{3}", hourly.ToString("c").PadRight(14)
						  ,weekly.ToString("c").PadRight(14)
						  ,monthly.ToString("c").PadRight(15)
						  ,yearly.ToString("c"));
			
	}
	
	private static void Run(int hourly, int max)
	{
			String[] breakdown =  new String[]{
				"Hourly",
				"Weekly",
				"Monthly",
				"Yearly",
			};
			
		foreach(var period in breakdown){
			Console.Write("{0}\t\t", period);
		}
				Console.WriteLine();
		
		for(int i=hourly; i<=max;i++)
		{
			Maths(i);
		}	
	}
	
	public static int[] Ask()
	{
		int[] values = new int[2];
		while(true)
			{
				Console.Write("Enter Starting Hourly amount>");
				String input = Console.ReadLine();
				Console.Write("Enter Max Hourly amount>");
				String sMax = Console.ReadLine();
				
				if(Int32.TryParse(input, out values[0]) && Int32.TryParse(sMax, out values[1])) break;
			}	
		return values;
	}
		public static void Main()
	{
			int[] values = Ask();
			
			while(values[0] > values[1]) 
			{
				Console.WriteLine("Your starting value is greater than you Ending value. Retry");
				values = Ask();
			}
			Run(values[0], values[1]);
	}
}




Running example: https://dotnetfiddle.net/dEr0ok

Is This A Good Question/Topic? 0
  • +

Replies To: I got bored

#2 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15175
  • View blog
  • Posts: 60,742
  • Joined: 12-June 08

Re: I got bored

Posted 31 August 2018 - 11:31 AM

What is this telling me, why does it not use LINQ, where is the multi-threading/tasking, and could it be done smaller?
Was This Post Helpful? 0
  • +
  • -

#3 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6992
  • View blog
  • Posts: 23,770
  • Joined: 05-May 12

Re: I got bored

Posted 31 August 2018 - 04:38 PM

My verbose version of the code above (with my own interpretation of how the data should be gathered and presented):
using System;
using System.Collections.Generic;
using System.Data;

public class Program
{
    const int HoursPerWeek  = 40;
    const int WeeksPerMonth = 4;
    const int WeeksPerYear  = 52;
    const int ColumnWidth   = 14;
    const int GutterWidth   = 2;
    const decimal Stepping  = 1.0m;

    static Dictionary<string, Func<decimal, decimal>> Columns = new Dictionary<string, Func<decimal, decimal>>()
    {
        ["Hourly"] = h => h,
        ["Weekly"] = h => h * HoursPerWeek,
        ["Monthly"] = h => h * HoursPerWeek * WeeksPerMonth,
        ["Yearly"] = h => h * HoursPerWeek * WeeksPerYear,
    };

    static DataTable ComputeRates(decimal hourly, decimal max, decimal step, Dictionary<string, Func<decimal, decimal>> columns)
    {
        var table = new DataTable();
        foreach (var name in columns.Keys)
            table.Columns.Add(name, typeof(decimal));

        for (var i = hourly; i <= max; i += step)
        {
            var row = table.NewRow();
            foreach (var kvp in columns)
                row[kvp.Key] = kvp.Value(i);
            table.Rows.Add(row);
        }
        return table;
    }

    static void PresentTable(DataTable table)
    {
        string gutter = "".PadRight(GutterWidth);

        for(int i = 0; i < table.Columns.Count; i++)
            Console.Write($"{table.Columns[i],ColumnWidth:s}{gutter}");
        Console.WriteLine();

        for (var i = 0; i < table.Rows.Count; i++)
        {
            for(var j = 0; j < table.Columns.Count; j++)
                Console.Write($"{table.Rows[i][j],ColumnWidth:c}{gutter}");
            Console.WriteLine();
        }
    }

    static bool TryGetDecimalInput(string prompt, out decimal value)
    {
        Console.Write(prompt);
        var input = Console.ReadLine();
        bool success = decimal.TryParse(input, out value);
        if (!success)
            Console.Error.WriteLine("Input could not be parsed as a decimal");
        return success;
    }

    static (decimal hourly, decimal max) GetHourlyAndMaximumRate()
    {
        decimal hourly;
        decimal max;
        while (!(TryGetDecimalInput("Enter Starting Hourly amount>", out hourly) &&
                 TryGetDecimalInput("Enter Maximum Hourly ammount>", out max)))
        {
            Console.WriteLine("Your starting value is greater than your ending value. Retry");
        }
        return (hourly, max);
    }

    public static void Main()
    {
        var (hourly, max) = GetHourlyAndMaximumRate();
        PresentTable(ComputeRates(hourly, max, Stepping, Columns));
    }
}



(Sorry, no Fiddle since I couldn't figure out how to make it handle C# 7.x's tuple values even while using Roslyn.)
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6992
  • View blog
  • Posts: 23,770
  • Joined: 05-May 12

Re: I got bored

Posted 31 August 2018 - 11:37 PM

And considering how much I hate DataSet and it's ilk, here's the version I would rather work with after had some time to give the code more thought:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using RateFunc = System.Func<decimal, decimal>;

public class Program
{
    const int HoursPerWeek  = 40;
    const int WeeksPerMonth = 4;
    const int WeeksPerYear  = 52;
    const decimal Stepping  = 1.0m;

    readonly TextReader _reader;
    readonly TextWriter _writer;
    readonly TextWriter _error;

    public Program(TextReader reader, TextWriter writer, TextWriter error)
    {
        _reader = reader;
        _writer = writer;
        _error = error;
    }

    Dictionary<string, RateFunc> Columns = new Dictionary<string, RateFunc>()
    {
        ["Hourly"]  = h => h,
        ["Weekly"]  = h => h * HoursPerWeek,
        ["Monthly"] = h => h * HoursPerWeek * WeeksPerMonth,
        ["Yearly"]  = h => h * HoursPerWeek * WeeksPerYear,
    };

    void PresentTable(IEnumerable<string> columnNames,
                      IEnumerable<IEnumerable<decimal>> rows)
    {
        _writer.WriteLine(columnNames.FormatColumns(c => c));
        foreach (var row in rows)
            _writer.WriteLine(row.FormatColumns(c => c.ToString("C")));
    }

    bool TryGetDecimalInput(string prompt, out decimal value)
    {
        _writer.Write(prompt);
        var input = _reader.ReadLine();
        bool success = decimal.TryParse(input, out value);
        if (!success)
            _error.WriteLine("Input could not be parsed as a decimal");
        return success;
    }

    (decimal min, decimal max) GetHourlyRateRange()
    {
        decimal min, max;
        while (!(TryGetDecimalInput("Enter Starting Hourly amount>", out min) &&
                 TryGetDecimalInput("Enter Maximum Hourly amount>", out max)))
        {
            _writer.WriteLine("Your starting value is greater than your ending value. Retry");
        }
        return (min, max);
    }

    public void Run()
    {
        var (min, max) = GetHourlyRateRange();
        PresentTable(Columns.Keys,
                     Extensions.Range(min, max, Stepping)
                               .Select(r => Columns.Values.Select(f => f(r))));
    }

    public static void Main()
    {
        new Program(Console.In, Console.Out, Console.Error).Run();
    }
}

public static class Extensions
{
    public static IEnumerable<decimal> Range(decimal min, decimal max, decimal step)
    {
        for (; min <= max; min += step)
            yield return min;
    }

    public static string FormatColumns<T>(this IEnumerable<T> columns,
                                          Func<T, string> format,
                                          int columnWidth = 14,
                                          int gutterWidth = 2)
    {
        return String.Join("".PadRight(gutterWidth),
                           columns.Select(v => format(v).PadLeft(columnWidth)));
    }
}



Still more verbose than the original, but I'm trying to maintain a separation of concerns.
Was This Post Helpful? 0
  • +
  • -

#5 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7468
  • View blog
  • Posts: 15,483
  • Joined: 16-October 07

Re: I got bored

Posted 01 September 2018 - 11:23 AM

This is my favorite kind of game.

Here's my first stab:
using System;
using System.Linq;

public class Program {
    private static void Run(int from, int to) {
        var groups = new(string, int, int)[] {
            ("Hourly", 1, 14), ("Weekly", 40, 14), ("Monthly", 40 * 4, 15), ("Yearly", 2080, 0)
        };
        Func<int, string> maths = (hourly) =>
            string.Join("", groups.Select(g => (g.Item2 * hourly).ToString("c").PadRight(g.Item3)));
        Console.WriteLine(string.Join("\t\t", groups.Select(g => g.Item1)));
        Console.WriteLine(string.Join("\n", Enumerable.Range(from, to - from + 1).Select(maths)));
    }
    private static void Run((int, int) x) => Run(x.Item1, x.Item2);

    private static int Ask(string prompt) {
        Console.Write(prompt);
        return int.TryParse(Console.ReadLine(), out int value) ? value : Ask(prompt);
    }

    private static (int, int) Ask() =>
        (Ask("Enter Starting Hourly amount>"), Ask("Enter Max Hourly amount>"));

    private static (int, int) AskGuard() {
        (var from, var to) = Ask();
        while (from > to) {
            Console.WriteLine("Your starting value is greater than you Ending value. Retry");
            (from, to) = Ask();
        }
        return (from, to);
    }

    public static void Main() {
        Run(AskGuard());
        Console.ReadLine();
    }
}



However, the print squish seems overkill... Maybe:
private static IEnumerable<string> Run(int hourly, int to) {
    Func<IEnumerable<object>, string> fmt = xs =>
        string.Join("", xs.Select(x => string.Format("{0,15:c}", x)));
    var groups = new(string, int)[] {
        ("Hourly", 1), ("Weekly", 40), ("Monthly", 40 * 4), ("Yearly", 2080)
    };
    yield return fmt(groups.Select(g => g.Item1));
    for (; hourly <= to; hourly++) {
        yield return fmt(groups.Select(x => x.Item2).Select(x => x * hourly).Cast<object>());
    }
}


Was This Post Helpful? 0
  • +
  • -

#6 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7468
  • View blog
  • Posts: 15,483
  • Joined: 16-October 07

Re: I got bored

Posted 02 September 2018 - 02:12 AM

Upon further consideration, I found this gave me the most joy:
static (string Name, int Factor) Hourly => ("Hourly", 1);
static (string Name, int Factor) Daily => ("Daily", Hourly.Factor * 8);
static (string Name, int Factor) Weekly => ("Weekly", Daily.Factor * 5);
static (string Name, int Factor) Monthly => ("Monthly", Weekly.Factor * 4);
static (string Name, int Factor) Yearly => ("Yearly", Weekly.Factor * 52);
private static IEnumerable<string> Run(int hourly, int max) {
    var factors = new []{ Hourly, Daily, Weekly, Monthly, Yearly };
    Func<IEnumerable<object>, string> fmt = xs => string.Join("", xs.Select(x => string.Format("{0,15:c}", x)));
    yield return fmt(factors.Select(x => x.Name));
    for(; hourly<=max; hourly++) {
        yield return fmt(factors.Select(x => hourly * x.Factor).Cast<object>());
    }
}


Was This Post Helpful? 1
  • +
  • -

#7 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6992
  • View blog
  • Posts: 23,770
  • Joined: 05-May 12

Re: I got bored

Posted 03 September 2018 - 05:24 PM

I like it too! Have you considered using nameof() so that you can geek out some more? :)
Was This Post Helpful? 0
  • +
  • -

#8 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7468
  • View blog
  • Posts: 15,483
  • Joined: 16-October 07

Re: I got bored

Posted 04 September 2018 - 05:03 AM

Hmm... so this won't work:
const int Hourly = 1;
const int Daily = Hourly * 8;
const int Weekly = Daily * 5;
const int Monthly = Weekly * 4;
const int Yearly = Weekly * 52;

private static IEnumerable<string> Run(int hourly, int max) {
    var factors = new[] { Hourly, Daily, Weekly, Monthly, Yearly };
    Func<IEnumerable<object>, string> fmt = xs => string.Join("", xs.Select(x => string.Format("{0,15:c}", x)));
    yield return fmt(factors.Select(x => nameof(x)));
    for (; hourly <= max; hourly++) {
        yield return fmt(factors.Select(x => hourly * x).Cast<object>());
    }
}


The name gets lost in the int array.

I suppose you could map the vars with the name of, but then you're going back to the beginning. You could register the values in a dictionary, but that offers other problems, including loosing order.

Hmm...
private static Lazy<IEnumerable<(string, int)>> Factors = new Lazy<IEnumerable<(string, int)>>(() => {
    var xs = new List<(string, int)>();
    Func<string, int> v = name => xs.First(x => x.Item1 == name).Item2;
    xs.Add(("Hourly", 1));
    xs.Add(("Daily", v("Hourly") * 8));
    xs.Add(("Weekly", v("Daily") * 5));
    xs.Add(("Monthly", v("Weekly") * 4));
    xs.Add(("Yearly ", v("Weekly") * 52));
    return xs;
    });

private static IEnumerable<string> Run(int hourly, int max) {
    Func<IEnumerable<object>, string> fmt = xs => string.Join("", xs.Select(x => string.Format("{0,15:c}", x)));
    yield return fmt(Factors.Value.Select(x => x.Item1));
    for (; hourly <= max; hourly++) {
        yield return fmt(Factors.Value.Select(x => x.Item2).Select(x => hourly * x).Cast<object>());
    }
}



See, this is how I get into trouble. It's way too easy to go down an over engineering rabbit hole.
Was This Post Helpful? 2
  • +
  • -

#9 astonecipher   User is offline

  • Senior Systems Engineer
  • member icon

Reputation: 2906
  • View blog
  • Posts: 11,328
  • Joined: 03-December 12

Re: I got bored

Posted 04 September 2018 - 05:48 AM

This makes me think code challenges should be reintroduced. Nothing even complex, just here is a problem, participate if you so desire.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1