DevPinoy.org
A Filipino Developers Community
   

Maximum Sub-array

rated by 0 users
This post has 22 Replies | 0 Followers

Top 25 Contributor
Posts 193
Points 3,315
jop Posted: 07-25-2007 7:21 PM

This challenge is lifted from RubyQuiz #131. You can visit that site if you need spoilers. :D


Given an array of integers, find the sub-array with maximum sum.

For example:

    array:              [-1, 2, 5, -1, 3, -2, 1]
    maximum sub-array:  [2, 5, -1, 3]

You can use any language you want.

Go.

[jop]

Top 10 Contributor
Posts 1,036
Points 23,965

my solution:

    public class MaxSubArray
    {
        public int[] GetMaxSubArrayFor(int[] input)
        {
            int offsetLength = 0;
            int offset = 0;
            int maxSum = int.MinValue;

            for (int candidateOffset = 0; candidateOffset < input.Length; candidateOffset++)
            {
                int currentSum = 0;
                for (int candidateLength = 1; candidateLength <= input.Length - candidateOffset; candidateLength++)
                {
                    currentSum += input[candidateOffset + candidateLength - 1];
                    if ((currentSum > maxSum) || ((currentSum == maxSum) && (candidateLength > offsetLength)))
                    {
                        maxSum = currentSum;
                        offsetLength = candidateLength;
                        offset = candidateOffset;
                    }
                }
            }
            return GetSubsetOf(input, offset, offsetLength);
        }

        public static int[] GetSubsetOf(int[] input, int offset, int length)
        {
            int[] outputArray = new int[length];
            for (int index = offset; index < offset + length; index++)
            {
                outputArray[index - offset] = input[index];
            }
            return outputArray;
        }
    }

note: edited to take into account leading/trailing zeroes

http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 5
Top 10 Contributor
Posts 1,036
Points 23,965

test suite:

    [TestFixture]
    public class TestMaxSubArray
    {
        private MaxSubArray subFinder;

        [SetUp]
        public void Init()
        {
            subFinder = new MaxSubArray();
        }

        [Test]
        public void ShouldHaveZeroSubsetIfBlank()
        {
            int[] sub = subFinder.GetMaxSubArrayFor(GetBlankInput());
            Assert.That(sub.Length, Is.EqualTo(0));
        }

        [Test]
        public void ShouldHaveOnlyOneIfAllNegative()
        {
            int[] sub = subFinder.GetMaxSubArrayFor(GetAllNegativeInput());
            Assert.That(sub.Length, Is.EqualTo(1));
            Assert.That(sub[0], Is.EqualTo(-1));
        }

        [Test]
        public void ShouldHaveWholeIfAllPositive()
        {
            int[] allPositive = GetAllPositiveInput();
            int[] sub = subFinder.GetMaxSubArrayFor(allPositive);
            Assert.That(sub, Is.EquivalentTo(allPositive));
        }

        [Test]
        public void ShouldGetJopsResult()
        {
            int[] jopSolution = {2, 5, -1, 3};
            int[] sub = subFinder.GetMaxSubArrayFor(GetJopTestInput());
            Assert.That(sub, Is.EquivalentTo(jopSolution));
        }

        private int[] GetBlankInput()
        {
            int[] blankInput = new int[0];
            return blankInput;
        }

        private int[] GetAllNegativeInput()
        {
            int[] allNegative = {-1, -2, -3, -4, -5};
            return allNegative;
        }

        private int[] GetAllPositiveInput()
        {
            int[] allPositive = {1, 2, 3, 4, 5, 6};
            return allPositive;
        }

        private int[] GetJopTestInput()
        {
            int[] jopTest = {-1, 2, 5, -1, 3, -2, 1};
            return jopTest;
        }
    }
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 5
Top 10 Contributor
Posts 1,036
Points 23,965
very procedural ba yun code? he he...parang daya lang yun TDD ko dyan eh. he he
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 20
Top 25 Contributor
Posts 193
Points 3,315
How about zeroes? e.g. [2,0,-1] and [-1,0,2]

[jop]

  • | Post Points: 20
Top 10 Contributor
Posts 1,036
Points 23,965
oo nga ano? di ko naconsider yan ah. dapat ba kasama sila sa result?
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 5
Top 10 Contributor
Posts 1,036
Points 23,965

here's my more OOP solution, utilizing two classes named ArrayWithSum and ListOfArrayWithSum. if my C# had extension methods now, this would have been shorter ;)

    public class ArrayWithSum : List<int>
    {
        public ArrayWithSum(IEnumerable<int> input)
            : base(input)
        {
        }
        public ArrayWithSum()
        {
        }

        public int Sum
        {
            get
            {
                int sum = 0;
                foreach (int item in this)
                {
                    sum += item;
                }
                return sum;
            }
        }

        public bool IsBlank
        {
            get
            {
                return (Count == 0);
            }
        }

        public bool IsBiggerThan(ArrayWithSum another)
        {
            return (Sum > another.Sum) ||
                   ((Sum == another.Sum) && (Count > another.Count)) ||
                   (!IsBlank && another.IsBlank);
        }

        public new ArrayWithSum GetRange(int index, int count)
        {
            return new ArrayWithSum(base.GetRange(index, count));
        }

        public ListOfArrayWithSum GetSubArrays()
        {
            ListOfArrayWithSum subArrays = new ListOfArrayWithSum();
            for (int index = 0; index < Count; index++)
            {
                for (int length = 1; length <= Count - index; length++)
                {
                    subArrays.Add(GetRange(index, length));
                }
            }
            return subArrays;
        }

        public ArrayWithSum GetMaxSubArray()
        {
            return GetSubArrays().GetMaxSubArray();
        }

    }
    public class ListOfArrayWithSum : List<ArrayWithSum>
    {
        public ListOfArrayWithSum(IEnumerable<ArrayWithSum> input) : base(input)
        {
        }
        public ListOfArrayWithSum()
        {
        }

        public ArrayWithSum GetMaxSubArray()
        {
            ArrayWithSum item = new ArrayWithSum();
            foreach (ArrayWithSum candidate in this)
            {
                if (candidate.IsBiggerThan(item))
                {
                    item = candidate;
                }
            }
            return item;
        }
    }
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 5
Top 10 Contributor
Posts 1,036
Points 23,965

and test cases for this "more OOP" solution...

    [TestFixture]
    public class TestNewMaxSubArray
    {
        [Test]
        public void TestCreateEnhancedArray()
        {
            ArrayWithSum arr = new ArrayWithSum(GetAllNegativeInput());
            Assert.That(arr.Sum, Is.EqualTo(-15));
        }

        [Test]
        public void TestGetSubsetOfArray()
        {
            ArrayWithSum arr = new ArrayWithSum(GetAllNegativeInput());
            ArrayWithSum subArr = arr.GetRange(2, 3);
            Assert.That(subArr.Sum, Is.EqualTo(-12));
        }

        [Test]
        public void TestGetRangesOfArrayWithSum()
        {
            ArrayWithSum arr = new ArrayWithSum(GetAllNegativeInput());
            ListOfArrayWithSum subArrays = arr.GetSubArrays();
            Assert.That(subArrays.Count, Is.EqualTo(15));
        }

        [Test]
        public void TestGetMaxSubArray()
        {
            ArrayWithSum arr = new ArrayWithSum(GetAllNegativeInput());
            ArrayWithSum maxSub = arr.GetSubArrays().GetMaxSubArray();
            Assert.That(maxSub.Count, Is.EqualTo(1));
            Assert.That(maxSub.Sum, Is.EqualTo(-1));
        }

        [Test]
        public void TestCase1()
        {
            int[] input = new int[0];
            ArrayWithSum maxSub = new ArrayWithSum(input).GetMaxSubArray();
            Assert.That(maxSub.Count, Is.EqualTo(0));
            Assert.That(maxSub.Sum, Is.EqualTo(0));
        }

        [Test]
        public void TestCase2()
        {
            int[] input = {-1, 2, 5, -1, 3, -2, 1};
            int[] solution = {2, 5, -1, 3};
            ArrayWithSum maxSub = new ArrayWithSum(input).GetMaxSubArray();
            Assert.That(maxSub.ToArray(), Is.EquivalentTo(solution));
        }

        [Test]
        public void TestCase3()
        {
            int[] input = {2, 0, -1};
            int[] solution = {2, 0};
            ArrayWithSum maxSub = new ArrayWithSum(input).GetMaxSubArray();
            Assert.That(maxSub.ToArray(), Is.EquivalentTo(solution));
        }

        [Test]
        public void TestCase4()
        {
            int[] input = {0, 2, 0, -1};
            int[] solution = {0, 2, 0};
            ArrayWithSum maxSub = new ArrayWithSum(input).GetMaxSubArray();
            Assert.That(maxSub.ToArray(), Is.EquivalentTo(solution));
        }

        private static int[] GetAllNegativeInput()
        {
            int[] allNegative = {-1, -2, -3, -4, -5};
            return allNegative;
        }
    }
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 20
Top 25 Contributor
Posts 193
Points 3,315

Here is my solution written using the Language of the Gods :D

TestMaxSubArray>>testMaxSubArray
    "Test cases"
    self should: [#(1 2 3 4 5) = #(1 2 3 4 5) maxSubArray].
    self should: [#(0 2) = #(-1 0 2) maxSubArray].
    self should: [#(2 0) = #(2 0 -1) maxSubArray].
    self should: [#(2 5 -1 3) = #(-1 2 5 -1 3 -2 1) maxSubArray].

Array>>maxSubArray
    "Add method to Array. Look for subarray with the highest sum"
    | result |
    result := #(0 ).
    self forEachSubArray: 
        [ :candidate |
            (candidate isGreaterThan: result)
                ifTrue: [result := candidate]].
    ^ result

Array>>forEachSubArray: aBlock 
    "Add method to Array. Execute aBlock for each subarray that can be found"
    1 to: self size do: [:start |
        start to: self size do: [:end | 
            aBlock value: (self copyFrom: start to: end)]].

Array>>isGreaterThan: anArray
    ^(self sum > anArray sum 
        or: [self sum = anArray sum 
            and: [self size > anArray size]]).

[jop]

  • | Post Points: 20
Top 10 Contributor
Posts 1,036
Points 23,965
we're not worthy!!! grabe nagmukhang basang sisiw yun solution ko kumpara sa yo (in smalltalk) ah! Stick out tongue
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 20
Top 25 Contributor
Posts 193
Points 3,315
cruizer:
we're not worthy!!! grabe nagmukhang basang sisiw yun solution ko kumpara sa yo (in smalltalk) ah! Stick out tongue
Yung C# version ko, kaparehas lang nung gawa mo kaya di ko na ipo-post.

[jop]

  • | Post Points: 20
Top 10 Contributor
Posts 2,038
Points 42,030

jop:
cruizer:
we're not worthy!!! grabe nagmukhang basang sisiw yun solution ko kumpara sa yo (in smalltalk) ah! Stick out tongue
Yung C# version ko, kaparehas lang nung gawa mo kaya di ko na ipo-post.

Oo nga! bangis nung kay jop! I tried doing this in C# but wasn't able to finish it due to time constraints. Lupet!

devpinoy sig

  • | Post Points: 35
Top 25 Contributor
Posts 193
Points 3,315
Anyone think this can be done in SQL?

[jop]

  • | Post Points: 5
Top 10 Contributor
Posts 1,036
Points 23,965
baka medyo kalawang ka pa keith dahil sa honeymoon, ha ha Stick out tongue
http://devpinoy.org/blogs/cruizer
Naglalayong buksan at palayain ang kamalayan ng Pinoy .NET developer
  • | Post Points: 20
Top 10 Contributor
Posts 2,038
Points 42,030

cruizer:
baka medyo kalawang ka pa keith dahil sa honeymoon, ha ha Stick out tongue

Hahah, I'm just not in the zone yet to work ;). Yes jop i think it can be done in SQL..

devpinoy sig

  • | Post Points: 20
Page 1 of 2 (23 items) 1 2 Next > | RSS
Copyright DevPinoy 2005-2008