public void When_logging_of_steps_enabled()
        {
            var sut = new RussianPeasantMultiplier(true);

            sut.Multiply(12, 45).Should().Equals(12 * 45);
            sut.Steps.Count.Should().Equals(4);
        }
        public Property CommutativeLaw(int x, int y)
        {
            // x * y = y * x
            var sut = new RussianPeasantMultiplier();

            return((sut.Multiply(x, y) == sut.Multiply(y, x)).ToProperty());
        }
        public void When_logging_of_steps_disabled()
        {
            var sut = new RussianPeasantMultiplier(false);

            sut.Multiply(67, 42).Should().Equals(67 * 42);
            sut.Steps.Count.Should().Equals(0);
        }
        public Property DistributiveLaw(int x, int y, int z)
        {
            // x * (y + z) = (x * y) + (x * z)
            var sut = new RussianPeasantMultiplier();

            return((sut.Multiply(x, y + z) == sut.Multiply(x, y) + sut.Multiply(x, z)).ToProperty());
        }
        public Property AssociativeLaw(int x, int y, int z)
        {
            // (x * y) * z = x * (y * z)
            var sut = new RussianPeasantMultiplier();

            return((sut.Multiply(sut.Multiply(x, y), z) == sut.Multiply(x, sut.Multiply(y, z))).ToProperty());
        }
        public void When_logging_of_steps_disabled()
        {
            var sut = new RussianPeasantMultiplier(false);

            Assert.Equal(67 * 42, sut.Multiply(67, 42));
            Assert.Equal(0, sut.Steps.Count);
        }
        public void When_logging_of_steps_enabled()
        {
            var sut = new RussianPeasantMultiplier(true);

            Assert.Equal(12 * 45, sut.Multiply(12, 45));
            Assert.Equal(4, sut.Steps.Count);
        }
        public Property NegationLaw(int x)
        {
            // -1 * x = -x where -1 * -1 = 1
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(-1, -1).Should().Equals(1);
            return((sut.Multiply(-1, x) == -x).ToProperty());
        }
        public void When_both_values_are_negative()
        {
            var sut     = new RussianPeasantMultiplier();
            var product = sut.Multiply(-42, -68);

            product.Should().Equals(42 * 68);
            product.Should().BePositive();
        }
        public void When_both_values_are_negative()
        {
            var sut     = new RussianPeasantMultiplier();
            var product = sut.Multiply(-42, -68);

            Assert.Equal(42 * 68, product);
            Assert.True(product > 0);
        }
        public void When_x1_is_negative()
        {
            var sut     = new RussianPeasantMultiplier();
            var product = sut.Multiply(-23, 45);

            Assert.Equal(-23 * 45, product);
            Assert.True(product < 0);
        }
        public void When_x1_is_negative()
        {
            var sut     = new RussianPeasantMultiplier();
            var product = sut.Multiply(-23, 45);

            product.Should().Equals(-23 * 45);
            product.Should().BeNegative();
        }
        public void When_absolute_value_of_negative_x1_is_greater_than_x2()
        {
            var       sut = new RussianPeasantMultiplier();
            const int x1  = -65;
            const int x2  = 35;

            Assert.Equal(-65 * 35, sut.Multiply(x1, x2));
            Assert.Equal(x2, sut.X1); //Assert arguments swapped
            Assert.Equal(x1, sut.X2);
        }
        public void When_multiplying_1_and_x()
        {
            //Arrange
            var sut = new RussianPeasantMultiplier();
            //Act
            var product = sut.Multiply(1, 2);

            //Assert
            Assert.Equal(2, product);
        }
        public Property IdentityLaw(int x)
        {
            // 1 * x = x
            // x * 1 = x    // right identity is also proven if commutative property holds
            // -1 * x = -x  // left negative identity also proven if negation property holds
            // x * -1 = -x  // right negative identity also proven if cummutative and negation holds
            var sut = new RussianPeasantMultiplier();

            return((sut.Multiply(1, x) == x).ToProperty());
        }
        public Property ZeroLaw(int x)
        {
            // Zero is the absorbing element for multiplication - as opposed to addition which does not have an absorbing element
            // https://en.wikipedia.org/wiki/Absorbing_element
            // 0 * x = 0
            // x * 0 = 0    //Right zero also proven if commutative property holds
            var sut = new RussianPeasantMultiplier();

            return((sut.Multiply(0, x) == 0).ToProperty());
        }
        public void When_absolute_value_of_negative_x1_is_greater_than_x2()
        {
            var       sut = new RussianPeasantMultiplier();
            const int x1  = -65;
            const int x2  = 35;

            sut.Multiply(x1, x2).Should().Equals(-65 * 35);
            sut.X1.Should().Equals(x2); //Assert arguments swapped
            sut.X2.Should().Equals(x1);
        }
        public Property NegativeOrderPreservationLaw(int x, int y, int z)
        {
            // Forall x < 0, if y > z then x * y < x * z
            var         sut      = new RussianPeasantMultiplier();
            var         lhs      = sut.Multiply(x, y);
            var         rhs      = sut.Multiply(x, z);
            Func <bool> property = () => lhs < rhs;

            return(property.When(x < 0 && y > z));
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Welcome to the Russian Peasant Multiplier!");

            var showSteps = GetYesNo("Would you like to see the steps? (y/n) ");

            russianPeasantMultiplier = new RussianPeasantMultiplier(showSteps);

            while (true)
            {
                if (!DoTheMultiplication(showSteps))
                {
                    break;
                }
            }

            //var x = int.Parse(args[0]);
            //var y = int.Parse(args[1]);
            //Console.WriteLine(Functional.Multiply(x, y));

            Console.ReadLine();
        }
        public void When_x1_is_larger_than_x2()
        {
            var sut = new RussianPeasantMultiplier();

            Assert.Equal(52 * 35, sut.Multiply(52, 35));
        }
        public void When_x1_is_smaller_than_x2()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(35, 52).Should().Equals(52 * 35);
        }
        public void When_x1_and_x2_is_0()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(0, 0).Should().Equals(0);
        }
        public void When_x1_is_smaller_than_x2()
        {
            var sut = new RussianPeasantMultiplier();

            Assert.Equal(52 * 35, sut.Multiply(35, 52));
        }
        public void When_multiplying_x_and_2()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(7, 2).Should().Equals(7 + 7);
        }
        public void When_multiplying_2_and_x()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(2, 5).Should().Equals(5 + 5);
        }
        public void When_multiplying_two_large_numbers()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(465, 23).Should().Equals(465 * 23);
        }
        public void ObjectOrientedMultiply()
        {
            var sut = new RussianPeasantMultiplier();

            sut.ExecutionTimeOf(s => s.Multiply(1000, 1000)).Should().BeLessThan(TimeSpan.FromMilliseconds(100));
        }
        public void When_x1_is_larger_than_x2()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(52, 35).Should().Equals(52 * 35);
        }
        public void When_multiplying_two_large_numbers()
        {
            var sut = new RussianPeasantMultiplier();

            Assert.Equal(465 * 23, sut.Multiply(465, 23));
        }
        public void When_multiplying_1_and_x()
        {
            var sut = new RussianPeasantMultiplier();

            sut.Multiply(1, 2).Should().Equals(2);
        }