Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pirate Game in Maths - Solve it with C#

I am trying to solve the following problem:

Some pirates have a chest full of treasure (gold coins)

It is late in the evening, so they decide to split it up in the morning

But, one of the pirates wakes up in the middle of the night concerned that the other pirates will steal his share so he decides to go divide the treasure himself.

He divides it into equal shares (one for each pirate). There is one coin left over, which he throws overboard. He takes his share, puts the other shares back in the chest, and returns to his cabin.

Another pirate wakes up and does the same thing. Yes, there is still one extra coin. Yes, he throws that coin overboard.

... Each pirate does this once during the night (yes, there is an extra coin and they throw it overboard each time) , and the next morning they wake up and divide the treasure into equal shares. There is one left over which they throw overboard. They each take their share and live happily ever after.

Given the number of pirates, what is the smallest number of coins that could have been in the treasure chest originally?

I tried the following, but any number greater than 8 brings it to its knees:

class Program
    {
        static long _input;
        static long _timesDivided;
        static string _output;

        static void Main()
        {
            Console.WriteLine("Enter the number of Pirates: ");

            var isValidInput = long.TryParse(Console.ReadLine(), out _input);

            if (!isValidInput)
            {
                Console.WriteLine("Please enter a valid number");
                Console.ReadKey();
                return;
            }

            Console.WriteLine("Caculating minimum treasure...\r\n \r\n");

            _timesDivided = _input + 1;

            var answer = CalculateTreasure();

            if (answer > 0)
                _output = string.Format("The minimum treasure is {0}", answer);
            else
                _output = "There was an error, please try another number";

            Console.WriteLine(_output);
            Console.ReadKey();
        }

        private static long CalculateTreasure()
        {
            long result = 0;

            try
            {
                while (true)
                {
                    result++;

                    while (true)
                    {
                        if (result % _input == 1)
                        {
                            break;
                        }
                        else
                        {
                            result++;
                        }
                    }

                    long treasure = result;

                    for (long i = 0; i < _timesDivided; i++)
                    {
                        var remainder = treasure % _input;

                        if (remainder != 1)
                        {
                            break;
                        }

                        var share = (treasure - remainder) / _input;

                        if (i == (_timesDivided - 1))
                        {
                            treasure = (treasure - (share * _input));

                            if (treasure == 1)
                                return result;
                        }
                        else
                        {
                            treasure = (treasure - share) - 1;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //log exception here
                return 0;
            }
        }
    }

I am fairly certain that every number must be a prime number, so I have also attempted the above with that in mind. However, I have not been able to figure out an efficient formula for solving this. My maths is simply too weak

EDIT

Thanks to the video Fr3d mentioned, I now have this for my CalculateTreasure method:

private static long CalculateTreasure()
        {
            try
            {
                long result = (long)Math.Pow((double)_input, (double)_timesDivided);

                while (true)
                {
                    result--;

                    while (true)
                    {
                        if (result % _input == 1)
                        {
                            break;
                        }
                        else
                        {
                            result--;
                        }
                    }

                    long treasure = result;

                    for (long i = 0; i < _timesDivided; i++)
                    {
                        var remainder = treasure % _input;

                        if (remainder != 1)
                        {
                            break;
                        }

                        var share = (treasure - remainder) / _input;

                        if (i == (_timesDivided - 1))
                        {
                            treasure = (treasure - (share * _input));

                            if (treasure == 1)
                                return result;
                        }
                        else
                        {
                            treasure = (treasure - share) - 1;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //log exception here
                return 0;
            }
        }

It is much improved, but still not 100% optimal

like image 350
user3574076 Avatar asked Nov 09 '22 11:11

user3574076


1 Answers

I think I found the correct formula:

using System;
using System.Numerics;

namespace PirateCoins
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine());
            Console.WriteLine(GetTreasure(n));
        }
        static BigInteger GetTreasure(int n)
        {
            BigInteger result = BigInteger.Pow(n, n + 1) - (n - 1);
            return result;
        }
    }
}

This is based from a sequence which was given 2 -> 7, 3 -> 79, 4 -> 1021, 5 -> 15621 .

like image 164
fsacer Avatar answered Nov 14 '22 21:11

fsacer