TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: JohnK on December 07, 2017, 09:52:34 AM

Title: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 07, 2017, 09:52:34 AM
I found an old challenge that should be fun to revisit. This challenge was from a friend of mine (his post) but he is no longer a member here so I will post his words below instead of trying to find a link to his post. I found this in one of my old files with the description and my entry into the challenge (I will post my entry later).

As usual, please post your solution in any language but please add comments to your code so other people can learn from your solution.

*** Cornbread ***
Given the array { 1, 9, -6, 5, -9, 3, 2, -7, 4, -5, 8, -2, 6}

Write the most efficient function you can which returns the sum of the largest possible sub array value and that sub arrays start and end indexes. The array may not be re-ordered it must stay as is. This can be solved in O(n) or in regular language: a single pass over each element of the array.

This should test your algorithm writing abilities not your ability to use your favorite language.
*** Cornbread ***
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 07, 2017, 11:00:29 AM
Spoiler Alert!

EDIT: Note, this code submission is incorrect.
Below was the code I had for the answer to the challenge Cornbread posted.
Code - Auto/Visual Lisp: [Select]
  1. (defun MaxSumofSubArray (arr / item inx-start inx-end cntr)
  2.   (setq cntr 0
  3.         item (car arr))
  4.   (mapcar
  5.     '(lambda (x)
  6.        (if (> x item)
  7.          ;; if we have a bigger number then the one stored already,
  8.          (setq inx-start
  9.                ;; find the start index, but...
  10.                (if (= cntr 0)
  11.                  ;; if the item is the first item in the list, then
  12.                  ;; dont go lower then zero
  13.                  0
  14.                  (1- cntr) )
  15.                inx-end
  16.                ;; find the end index, but...
  17.                (if (eq cntr (1- (length arr)))
  18.                  ;; if the item is the last item in the list, then
  19.                  ;; dont go any higher then the length of the list
  20.                  (1- (length arr))
  21.                  (1+ (1+ cntr)) )
  22.                item x
  23.                cntr (1+ cntr)
  24.                )
  25.          ;; if we have a smaller number, then the one we have stored
  26.          (setq cntr (1+ cntr))
  27.          )
  28.        )
  29.     arr
  30.     )
  31.  (list item inx-start inx-end)
  32. )

EDIT: This return value is incorrect.
Code: [Select]
(MaxSumofSubArray '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 6))
(9 0 3)

EDIT: The correct return value should be: 12 10 12


Title: Re: (Challenge) Max Sum of Sub Array
Post by: roy_043 on December 08, 2017, 05:53:47 AM
I may have misunderstood, but shouldn't the answer be:
Code: [Select]
(10 0 1)?
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 08, 2017, 07:18:18 AM
I may not have had the correct answer saved in my old file but I remember us all writing several versions trying to find the right answer. It was a really fun and confusing challenge (that much I remember). This came from a professional CS, so I wouldn't expect it to be that easy.
Title: Re: (Challenge) Max Sum of Sub Array
Post by: roy_043 on December 08, 2017, 07:32:51 AM
So what should the answer be?
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 08, 2017, 07:45:18 AM
I'm trying to figure that out right now. Do you want just the answer or how I got that (my "key" so to speak) as well?
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 08, 2017, 07:46:28 AM
The correct answer/return value should be: 12 10 12
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 08, 2017, 08:02:46 AM
Now I understand the problem again I need to work on my code and I already see that I am missing a big chunk of it. I will try and get to redoing my code throughout the day.
Title: Re: (Challenge) Max Sum of Sub Array
Post by: roy_043 on December 08, 2017, 10:05:28 AM
OK. The answer should indeed be (12 10 12).

Here is my suggestion:
Code - Auto/Visual Lisp: [Select]
  1. ; (Roy_MaxSumofSubList '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 6))    => (12 10 12)
  2. ; (Roy_MaxSumofSubList '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 12 6)) => (24 10 13)
  3. (defun Roy_MaxSumofSubList (lst / idx ret sub tmp)
  4.   (setq idx 0)
  5.   (repeat (length lst)
  6.     (setq sub (reverse lst))
  7.     (repeat (1- (length sub))
  8.       (if (> (setq tmp (apply '+ sub)) (car ret))
  9.         (setq ret (list tmp idx (+ idx (length sub) -1)))
  10.       )
  11.       (setq sub (cdr sub))
  12.     )
  13.     (setq idx (1+ idx))
  14.     (setq lst (cdr lst))
  15.   )
  16.   ret
  17. )
Title: Re: (Challenge) Max Sum of Sub Array
Post by: roy_043 on December 08, 2017, 02:55:06 PM
Another:
Code - Auto/Visual Lisp: [Select]
  1. (defun Roy_MaxSumofSubList_2 (lst / idx ret tmp)
  2.   (setq tmp (setq ret (list (car lst) 0 0)))
  3.   (setq idx 0)
  4.   (foreach itm (cdr lst)
  5.     (setq idx (1+ idx))
  6.     (cond
  7.       ((not tmp)
  8.         (setq tmp (list itm idx idx))
  9.       )
  10.       ((>= 0 (+ itm (car tmp)))
  11.         (setq tmp nil)
  12.       )
  13.       (T
  14.         (if (and (minusp itm) (> (car tmp) (car ret))) (setq ret tmp))
  15.         (setq tmp (list (+ itm (car tmp)) (cadr tmp) idx))
  16.       )
  17.     )
  18.   )
  19.   (if (> (car tmp) (car ret)) tmp ret)
  20. )
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 08, 2017, 03:59:29 PM
Nice ones!

I haven't been able to do much today (nose deep in specifications all day) after I initially tried to modify my code; I broke it several times just trying to add simple changes (boy, am I rusty!).
Title: Re: (Challenge) Max Sum of Sub Array
Post by: Lee Mac on December 08, 2017, 04:23:40 PM
Another:
Code - Auto/Visual Lisp: [Select]
  1. (defun Roy_MaxSumofSubList_2 (lst / idx ret tmp)
  2.     < ... >
  3. )

Very good Roy  :-)
Title: Re: (Challenge) Max Sum of Sub Array
Post by: VovKa on December 08, 2017, 05:38:09 PM
Code: [Select]
(Roy_MaxSumofSubList_2 '(2 -2 -2 3))
Title: Re: (Challenge) Max Sum of Sub Array
Post by: Lee Mac on December 08, 2017, 06:36:14 PM
Quick fix could be:
Code - Auto/Visual Lisp: [Select]
  1. (if (< 0 itm) (setq tmp (list itm idx idx)))

Well spotted VovKa.
Title: Re: (Challenge) Max Sum of Sub Array
Post by: roy_043 on December 09, 2017, 05:15:36 AM
Thank you all for your comments. :-)

Improved versions of my functions (the first one would also fail with VovKa's test case):
Code - Auto/Visual Lisp: [Select]
  1. ; (Roy_MaxSumOfSubList_1B '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 6))    => (12 10 12)
  2. ; (Roy_MaxSumOfSubList_1B '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 12 6)) => (24 10 13)
  3. ; (Roy_MaxSumOfSubList_1B '(2 -2 -2 3))                         => (3 3 3)
  4. (defun Roy_MaxSumOfSubList_1B (lst / idx ret sub tmp)
  5.   (setq idx 0)
  6.   (repeat (length lst)
  7.     (setq sub (reverse lst))
  8.     (repeat (length sub)
  9.       (if (> (setq tmp (apply '+ sub)) (car ret))
  10.         (setq ret (list tmp idx (+ idx (length sub) -1)))
  11.       )
  12.       (setq sub (cdr sub))
  13.     )
  14.     (setq idx (1+ idx))
  15.     (setq lst (cdr lst))
  16.   )
  17.   ret
  18. )
  19.  
  20. ; (Roy_MaxSumOfSubList_2B '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 6))    => (12 10 12)
  21. ; (Roy_MaxSumOfSubList_2B '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 12 6)) => (24 10 13)
  22. ; (Roy_MaxSumOfSubList_2B '(2 -2 -2 3))                         => (3 3 3)
  23. (defun Roy_MaxSumOfSubList_2B (lst / idx ret tmp)
  24.   (setq tmp (setq ret (list (car lst) 0 0)))
  25.   (setq idx 0)
  26.   (foreach itm (cdr lst)
  27.     (setq idx (1+ idx))
  28.     (cond
  29.       ((not tmp)
  30.         (setq tmp (list itm idx idx))
  31.       )
  32.       ((>= 0 (+ itm (car tmp)))
  33.         (setq tmp nil)
  34.       )
  35.       ((and (>= 0 (car tmp)) (> itm (car tmp)))
  36.         (setq tmp (list itm idx idx))
  37.       )
  38.       (T
  39.         (if (and (>= 0 itm) (> (car tmp) (car ret))) (setq ret tmp))
  40.         (setq tmp (list (+ itm (car tmp)) (cadr tmp) idx))
  41.       )
  42.     )
  43.   )
  44.   (if (> (car tmp) (car ret)) tmp ret)
  45. )
Title: Re: (Challenge) Max Sum of Sub Array
Post by: Lee Mac on December 09, 2017, 10:22:29 AM
Extending Roy's method, rather than testing for negation, I think the loop could be reduced to testing whether the next element improves the overall sum, i.e.:

Code - Auto/Visual Lisp: [Select]
  1. (defun LM_maxsublist ( lst / idx rtn tmp )
  2.     (setq rtn (list (car lst) 0 0)
  3.           tmp rtn
  4.           idx 1
  5.     )
  6.     (foreach itm (cdr lst)
  7.         (if (< (+ (car tmp) itm) itm)
  8.             (setq tmp (list itm idx idx))
  9.             (setq tmp (list (+ (car tmp) itm) (cadr tmp) idx))
  10.         )
  11.         (if (< (car rtn) (car tmp)) (setq rtn tmp))
  12.         (setq idx (1+ idx))
  13.     )
  14.     rtn
  15. )

Code - Auto/Visual Lisp: [Select]
  1. _$ (LM_maxsublist '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 6))
  2. (12 10 12)
  3. _$ (LM_maxsublist '(1 9 -6 5 -9 3 2 -7 4 -5 8 -2 12 6))
  4. (24 10 13)
  5. _$ (LM_maxsublist '(2 -2 -2 3))
  6. (3 3 3)
Title: Re: (Challenge) Max Sum of Sub Array
Post by: JohnK on December 09, 2017, 08:33:22 PM
Please add comments to your code entries.
Title: Re: (Challenge) Max Sum of Sub Array
Post by: roy_043 on December 10, 2017, 04:42:49 AM
Lee's code shows that I have been seriously overthinking this.
Of course now I'll have to do some more thinking... :-D
Title: Re: (Challenge) Max Sum of Sub Array
Post by: Lee Mac on December 10, 2017, 07:01:25 AM
Please add comments to your code entries.

A commented version:
Code - Auto/Visual Lisp: [Select]
  1. (defun LM_maxsublist ( lst / idx rtn tmp )
  2.     ;; Define function and declare arguments & local variables
  3.  
  4.     ;; Initialise variables
  5.     (setq
  6.         ;; 'rtn' holds the value that will eventually be returned by the function
  7.         rtn (list (car lst) 0 0)
  8.         ;; 'tmp' holds the comparison value to test whether each item improves the overall sum, initialised to the same value as 'rtn'
  9.         tmp rtn
  10.         ;; Index variable initialised to 1 as we've already processed the first item
  11.         idx 1
  12.     ) ;; end setq
  13.  
  14.     ;; For every other item in the list
  15.     (foreach itm (cdr lst)
  16.         ;; If the item is greater than the current sum plus the item
  17.         (if (< (+ (car tmp) itm) itm)
  18.             ;; Then all previous items would contribute negatively to the sum, so start the sublist at this item
  19.             (setq tmp (list itm idx idx))
  20.             ;; Else add this item to the current sum and update the upper index
  21.             (setq tmp (list (+ (car tmp) itm) (cadr tmp) idx))
  22.         ) ;; end if
  23.  
  24.         ;; If the current sum is greater than our current maximum
  25.         (if (< (car rtn) (car tmp))
  26.             ;; Then update the current maximum as we've found something better
  27.             (setq rtn tmp)
  28.         ) ;; end if
  29.  
  30.         ;; Increment the index variable for each item processed
  31.         (setq idx (1+ idx))
  32.     ) ;; end foreach
  33.  
  34.     ;; Return the maximum sum obtained and corresponding indexes
  35.     rtn
  36. ) ;; end defun