Efficient program to print/return all increasing subsequences of size 3 in an array - algorithm

Given an array like
1, 6, 5, 2, 3, 4
we need to print
1 2 3
1 3 4
1 2 4
2 3 4
What is the best way to do this?
Is this dynamic programming?
Is there a better way to do than the bruteforce O(n3)? I am sure there is.
The reason I say dynamic programming is because I can see this as something like
for '1' (print all results of sub problem of the rest of the array with subsequences of size 2).
for '2' (print all results of sub problems of the rest of the array with subseqences of size 2)
and go on like this.
However, there is a lot of overlap in the above two results, so we need to find an efficient way of reusing that, I guess.
Well, these are just random thoughts. You can correct me with the right appraoch.
OK, let me correct, if not print, I need the different increasing sequences returned. My point is, I need to find an approach to get to these sequences in the most efficient way.

You can walk through the array and remember what partial sequences are possible until the current point. Print and forget any sequences that reach length 3.
Example:
(1 6 5 2 3 4)
^
remember ((1))
(1 6 5 2 3 4)
^
remember ((1) (1 6) (6))
(1 6 5 2 3 4)
^
remember ((1) (1 6) (6) (1 5) (5))
(1 6 5 2 3 4)
^
remember ((1) (1 6) (6) (1 5) (5) (1 2) (2))
(1 6 5 2 3 4)
^
remember ((1) (1 6) (6) (1 5) (5) (1 2) (2) (1 3) (1 2 3) (2 3) (3))
print and forget (1 2 3)
remember ((1) (1 6) (6) (1 5) (5) (1 2) (2) (1 3) (2 3) (3))
(1 6 5 2 3 4)
^
remember ((1) (1 6) (6) (1 5) (5) (1 2) (2) (1 3) (2 3) (3) (1 4) (1 2 4) (2 4)
(1 3 4) (2 3 4) (3 4) (4))
print and forget (1 2 4)
print and forget (1 3 4)
print and forget (2 3 4)
done.
The challenge seems to lie in the choice of an appropriate data structure for the remembered subsequences.

In the generalized case you have to calculate the complexity based on two things:
1- Count of input numbers (I will call it b)
2- Length of output (I will call it d)
A generalized method that I can think of, is to construct an analogous graph to the problem in O(n^2):
If a larger number comes after a smaller number, There is a directed edge from smaller one to it.
Now in order to find all sequences of length d, You need to start from each number and output all paths of length (d - 1).
If you use a traversal method like BFS the complexity will be less than O(d x (b ^ (d - 1))).
However you can use adjacent matrix multiplication to find the paths of length d, which will bring the complexity down to something less than O((d - 2) x (b ^ 3)). (Nth power of an adjacency matrix will tell you how many paths exist from each node to another with length of N).
There are algorithms to reduce square matrix multiplication complexity a bit.

Create a list of ordered pairs (a,b) such that a<b and Index(a) < Index(b). O(n^2)
Sort this list (on either a or b -- doesn't matter) in O(n^2log(n)). Can be made O(nlog(n)) depending on data structure.
For each element in the list, find all matching ordered pairs using binary search -- worst case O(n^3log(n)), average case O(n^2log(n))

Related

Dynamic programming :how to solve all combination ordered coin change problem for large input

I have a challenge to find number of ways to get a sum of a given number from an array containing coins. For example:
coins: {2,3,5,7}
sum: 8
total ways: 6 -> (2 + 2 + 2 + 2), (2 + 3 + 3), (3 + 2 + 3), (3 + 3 + 2), (3 + 5), and (5 + 3).
I have the solution that works using dp pseudo code:
build an array ar of size "sum"
ar[0]=1
for i = 1 to sum do:
ar[i]=ar[i-2]+ar[i-3]+ar[i-5]+ar[i-7]
return ar[sum]
As mentioned this code works fine, but the platform I am running this in can have sum as large as 1019, and as expected it gives me a timeout. Is there any other way this can be dealt with? I have even tried to reduce the size of the array when it goes beyond size i-largest value in coins. But that as well times out.

Scheme making matrix

I am new to scheme and I'm having problems with matrices in Scheme. I need to create a function that takes one big and one small square matrices (with the condition: the small's length should be divisor of big one) and make a new matrix with doing an operation on the big one with small one. I've successfully split the big matrix to size that I wanted and I’m successfully operating on it to get the result.
Here is how I did it:
(define (matrix-op big small x y)
(if (< y (/ (length big) (length small))))
(if (< x (/ (length big) (length small)))
(cons (calculate (split-y (split-x big small x) small y) small)
(matrix-op big small (+ x 1) y))
(matrix-op big small 0 (+ y 1)) ; <- this is where i need to split
)
'()
)
)
My calculate function returns only 1 atomic value so when I run the function like this it gives me an output like '(val val val val), but what i want is formatting the output like '((val val) (val val)). How can I do it? Thanks in advance.
I realized that I couldn't explain the problem properly. What i want to have is a function that takes two different square matrices one big and one small, Splits the big one to same size as smaller one, operates on them to create a new matrix that has the size m/n if the big one is mxm and small one is nxn. Example:
big '( small '(
(8 0 3 1 5 3 2 2) (8 4)
(7 1 1 4 3 7 1 4) (9 5)
(1 3 7 4 3 6 6 3) )
(0 9 8 6 5 6 4 3)
(1 7 6 9 6 6 7 2)
(5 7 1 0 2 9 5 3)
(0 5 4 6 6 6 3 0)
(3 6 2 7 7 5 7 0)
)
I need to split big over the same size as small and calculate results like:
for x=0 y=0 part is '( calculate result is 5
(8 0)
(7 1)
)
for x=1 y=0 part is '( calculate result is 2
(3 1)
(1 4)
)
I actually did returned the results calculated but with the method i gave above my return was like '(5 2 4 2 2 6 4 4 4 3 5 4 2 4 6 3) but I wanted to return as:
'(
(5 2 4 2)
(2 6 4 4)
(4 3 5 4)
(2 4 6 3)
)
So how can I manage to split the return list where i want to split?
I think you are trying to do too much at once. It is always OK to split a bigger problem into a smaller problem.
If I understand yours, the idea is to take two square matrics, one of which may be some multiple of the other’s dimensions, and perform a pair-wise operation on the elements. For example:
'((1 2 3) '((1 2 3) '((7 7 7) '(( 8 9 10)
(4 5 6) + '((7)) --> (4 5 6) + (7 7 7) --> (11 12 13)
(7 8 9)) (7 8 9)) (7 7 7)) (14 15 16))
I will continue with the assumption that this is what is desired.
Notice that if the two matrices were the same size, a simple nested map would easily combine all elements. What is left is the problem of the different sizes.
Solve that and you are golden.
Recap:
(define (f op small-M big-M)
(f-apply-pairwise-op
op
(f-biggify small-M (/ (length big-M) (length small-M)))
big-M))
Now you have broken the problem into two smaller pieces:
(define (f-apply-pairwise-op op A B) ...) ; produces pairwise 'A op B'
(define (f-biggify M n) ...) ; tile M n times wider and taller
Good luck!

Preserving list structure with sorting a list of sublists in Lisp [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
So I have list structure as follows:
(defparameter *list* '( ((2 2 2) (0.1))
((5 5 5) (0.4))
((1 1 1) (1.2))
((3 3 3) (3.4))
((4 4 4) (4.5)) )
I want to sort it where it returns an output of
'( ((1 1 1) (1.2))
((2 2 2) (0.1))
((3 3 3) (3.4))
((4 4 4) (4.5)) )
So here is my attempt:
(sort *list*
#'(lambda (a b)
(< (squared a '(0 0 0))
(squared b '(0 0 0))))
:key #'first)
Where squared takes in two lists and calculates the squared distance of each element and sums them (ie (squared '(1 2 3) '(0 3 5)) => 48))
I am sorting the list of lists by its first element of the sublist '(# # #) and calculating the distance from '(0 0 0) then sorting by that distance.
But my attempt outputs the following => ((1) (1 1 1) (2) (3) (2 2 2) (4) (5) (3 3 3) (4 4 4) (5 5 5))
How do I sort by '(# # #) but also preserve the list structure? Also using Common Lisp!
Thank you!
EDIT
I had typed into lisp wrong but correctly into this forum. I had typed list as the following
(defparameter list '( (2 2 2) (0.1)
(5 5 5) (0.4)
(1 1 1) (1.2)
(3 3 3) (3.4)
(4 4 4) (4.5) ))
Careful: sort may destroy the input data. Your input as shown here contains literal data. Modifying literal data has undefined consequences. Use copy-tree or copy-list to create non-literal from literal data.
Actually my first attempt works! I just typed in list incorrectly (forgot some parenthesis). So it sorts and maintains the structure!

sorting integers with restrictions

if we have an array of integers then how can we determine the minimum steps required to sort them(in ascending order) if the only allowed operation per step is : moving the elements to either extremes?
E.g if we have
7 8 9 11 1 10
then in 1st step one can move 11 to right end and in second step move 1 to left end to get 1 7 8 9 10 11 . Hence total steps = 2
Can bubble sort be applied here? but the worst case complexity would be O(n^2) then. So how can we do more efficiently?
Thanks.
Here is a solution that takes O(n log n) time, O(n) auxiliary space, and exactly n MoveToFront operations.
Given the input array, A, Make a second array, B, with value/index pairs, like so...
7 8 9 11 1 10 -> (7 0) (8 1) (9 2) (11 3) (1 4) (10 5)
[this step takes O(n) time and O(n) space]
then sort B in descending order of the value of each pair...
(7 0) (8 1) (9 2) (11 3) (1 4) (10 5) -> (11 3) (10 5) (9 2) (8 1) (7 0) (1 4)
[this step takes O(n log n) time]
prepare a binary search tree, T.
Now for each element in B do the following...
Let I be the index of this element.
Let V be the sum of I and the number of elements in T that are greater than I.
Do a MoveToFront operation on the Vth element of A.
Add I to T.
[Both of the operations on T take O(log n) time]
Here is this algorithm working on your example array
(11 3)
I := 3
V := 3 + 0 = 3
MoveToFront(3): 7 8 9 11 1 10 -> 11 7 8 9 1 10
T: () -> (3)
(10 5)
I := 5
V := 5 + 0 = 5
MoveToFront(5): 11 7 8 9 1 10 -> 10 11 7 8 9 1
T: (3) -> (3 5)
(9 2)
I := 2
V := 2 + 2 = 4
MoveToFront(4): 10 11 7 8 9 1 -> 9 10 11 7 8 1
T: (3 5) -> (2 3 5)
(8 1)
I := 1
V := 1 + 3 = 4
MoveToFront(4): 9 10 11 7 8 1 -> 8 9 10 11 7 1
T: (2 3 5) -> (1 2 3 5)
(7 0)
I := 0
V := 0 + 4 = 4
MoveToFront(4): 8 9 10 11 7 1 -> 7 8 9 10 11 1
T: (1 2 3 5) -> (0 1 2 3 5)
(1 4)
I := 4
V := 4 + 1 = 5
MoveToFront(5): 7 8 9 10 11 1 -> 1 7 8 9 10 11
T: (0 1 2 3 5) -> (0 1 2 3 4 5)
I imagine you can find ways to sort these arrays that use fewer than n MoveToFront/Back operations, but I don't think you can find those in less than O(n log n) time. If those operations are slow, though, then it might be worth using an algorithm that takes more time to plan so you can do fewer of those operations.
Can you clarify this problem a little bit? When you say list, do you mean a linked list or do you mean an array? If it's not a linked list, I'm a little confused by the limited operation set. If it is a linked list you can probably modify quicksort which runs in average case O(nlgn) time.
Essentially the data structure you are mentioning is a linked list. For linked lists you can use quicksort or mergesort ( O(nlogn) ).
That doesn't sound to me like a sorting problem. You need to just find how many movements you need to do, but you don't need to sort the array. I bet that could be done faster than O(n log n)
I propose such solution:
just count how many a[i] > a[i - 1]. And that will be your result.
Argumentation:
If you have a[i] > a[i-1], it means, that either a[i] or a[i-1] aren't in their places. So you can:
1) move a[i-1] to the beginning of the array
2) move a[i] to the end of the array.
Upd. You need to define which a[i] or a[i-1] are you moving, as for your example for the array: 7 8 9 11 1 10 you have two comparations, that shows what aren't in place: 11 > 1 and 11 > 10. So that is definetely a task for dynamic programming. But, it is still faster then O(n log n)

Sum of numbers in a list using Scheme

I want to sum the numbers in a list without using recursion. I know you can sum a list of numbers like this
(+ num1 num2 ... numN)
but what if you have a list L which equals to '(num1 num2 ... numN)
is there a way to make + take the numbers in this list as arguments. I need to do this without recursion or helper functions.
Sure, just use apply:
(apply + '(1 2 3 4 5 6)) ; same as (+ 1 2 3 4 5 6)
(apply + 1 2 3 '(4 5 6)) ; ditto
(apply + 1 2 3 4 5 '(6)) ; ditto
(apply + 1 2 3 4 5 6 '()) ; ditto
The general answer to the question you seem to be asking -- how to take a list and use it as the arguments -- is apply, as Chris Jester-Young answered.
However, for this particular question, there might some other considerations. You may want to sum lists of arbitrary size. However, implementations often have some limit of the number of arguments you can call a function with. A more reliable solution may be to use some kind of fold function (various implementations have different fold functions) to fold + over the list.

Resources