Merge sort - four sorted parts in one array - c++

I have one array where are 4 sorted parts. For example
int array[20] = {1,4,7,8,10,2,3,6,8,11,1,2,7,8,9,3,4,9,10,13}
What I need to do is use merge sort on first 2 sorted parts (1,4,7,8,10 and 2,3,6,8,11) and then for second 2 sorted parts (1,2,7,8,9 and 3,4,9,10,13). Then I need to merge these 2 sorted parts into one sorted array.
I tried to use these piece of code, but there is something wrong.
void Merge(int *array, int *aux, int left, int right)
{
int middleIndex = (left + right) / 2;
int leftIndex = left;
int rightIndex = middleIndex + 1;
int auxIndex = left;
while (leftIndex <= middleIndex && rightIndex <= right)
{
if (array[leftIndex] >= array[rightIndex])
{
aux[auxIndex] = array[leftIndex++];
}
else
{
aux[auxIndex] = array[rightIndex++];
}
auxIndex++;
}
while (leftIndex <= middleIndex)
{
aux[auxIndex] = array[leftIndex++];
auxIndex++;
}
while (rightIndex <= right)
{
aux[auxIndex] = array[rightIndex++];
auxIndex++;
}
}
Any idea how to modify this, or write it better? Thanks

import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] sortArr1 = merge(new int[] {1 , 4 , 7 , 8 , 10} , new int[] {2 , 3 , 6 , 8 , 11} );
System.out.println("Merging of sorted array " +Arrays.toString(sortArr1));
int[] sortArr2 = merge(new int[] {1 , 2 , 7 , 8 , 9} , new int[] {3 , 4 , 9 , 10 , 13} );
System.out.println("Merging of sorted array " +Arrays.toString(sortArr2));
int[] finalSort = merge(sortArr1 , sortArr2);
System.out.println("Merging of sorted array " +Arrays.toString(finalSort));
}
public static int[] merge(int[] arr1 , int[] arr2) {
int[] sort = new int[arr1.length + arr2.length];
int j = 0;
int k = 0;
for(int i = 0 ; i < sort.length ; i++ ) {
if(j <= (arr1.length - 1) && k <= (arr2.length - 1)) {
if(arr1[j] > arr2[k]) {
sort[i] = arr2[k++];
}else {
sort[i] = arr1[j++];
}
}else if(j <= (arr1.length - 1)) {
sort[i] = arr1[j++];
}else if(k <= (arr2.length - 1)){
sort[i] = arr2[k++];
}
}
return sort;
}
}
Output of the program is :
Merging of sorted array [1, 2, 3, 4, 6, 7, 8, 8, 10, 11]
Merging of sorted array [1, 2, 3, 4, 7, 8, 9, 9, 10, 13]
Merging of sorted array [1, 1, 2, 2, 3, 3, 4, 4, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 13]

Any idea how to modify this, or write it better? Thanks
Since the ranges are already sorted, and you know where the ranges start and end, use std::inplace_merge:
#include <algorithm>
#include <iostream>
#include <iterator>
int array[20] = {1,4,7,8,10,2,3,6,8,11,1,2,7,8,9,3,4,9,10,13};
using namespace std;
void MergeSort(int *arr, int start1, int start2, int start3,
int start4, int size)
{
std::inplace_merge(arr + start1, arr + start2, arr + start3);
std::inplace_merge(arr + start3, arr + start4, arr + size);
std::inplace_merge(array, array + start3, arr + size);
}
int main()
{
MergeSort(array, 0, 5, 10, 15, 20);
std::copy(array, array + 20, ostream_iterator<int>(cout, " "));
}
Live Example

Related

How do i remove duplicates from this recursion code? Many 6-sided dice will be rolled and print only unique combinations that add up to a desired sum

in the following code, I'm able to print all the dice combinations that add up to a desired sum. I'd like some help in tweaking the code to remove the duplicate entries.
void rep(int n, string ans, int currentSum, int targetSum)
{
if(n==0)
{
if(currentSum==targetSum)
cout << "{" << ans << "}"<<endl;
}
else
{
for(int i=1 ; i<=6 ; i++)
{
if(n>1)
{
rep(n-1, ans + to_string(i) + ", ", currentSum+i, targetSum);
}
else
{
rep(n-1, ans + to_string(i), currentSum+i, targetSum);
}
}
}
}
void ManyDiceSum(int howManyDice, int targetSum)
{
if(howManyDice>0)
rep(howManyDice,"",0,targetSum);
}
int main()
{
int howManyDice, targetSum;
howManyDice=3;
targetSum=7;
ManyDiceSum(howManyDice, targetSum);
return 0;
}
Output for 3 dice and target sum of 7 should be:
{1, 1, 5}
{1, 2, 4}
{1, 3, 3}
{2, 2, 3}
But, my code is displaying all combinations:
{1, 1, 5}
{1, 2, 4}
{1, 3, 3}
{1, 4, 2}
{1, 5, 1}
{2, 1, 4}
{2, 2, 3}
{2, 3, 2}
{2, 4, 1}
{3, 1, 3}
{3, 2, 2}
{3, 3, 1}
{4, 1, 2}
{4, 2, 1}
{5, 1, 1}
Constraints are: It has to use recursion and use only 1 loop if
necessary.
First of all you do not need to pass both target and current sum to the function, only target is enough, and checking it first will speed up whole process significantly:
void rep( int n, int target, std::string ans = std::string(), int last = 1 )
{
if( n == 0 ) {
if( target == 0 )
std::cout << "{" << ans << "}" << std::endl;
return;
}
const auto limit = std::min( 6, target );
// or even following, but not sure this is quite right though
//const auto limit = std::min( 6, target - n * last );
for( int i = last ; i <= limit; ++i )
rep(n-1, target - i, ans + to_string(i) + ( n > 1 ? ", " : "" ), i );
}
void ManyDiceSum( int howManyDice, int TargetSum )
{
if (howManyDice > 0)
rep( howManyDice, TargetSum );
}
and to avoid duplicates continue from the last number you started.
A exemplary solution based on #Jarod42's comment:
void rep(int n, std::string ans, int currentSum, int TargetSum, int startFrom) {
if (n == 0) {
if (currentSum == TargetSum)
std::cout << "{" << ans << "}" << std::endl;
} else
for (int i = startFrom; i <= 6; i++)
if (n > 1)
rep(n-1, ans + to_string(i) + ", ", currentSum + i, TargetSum, i);
else
rep(n-1, ans + to_string(i), currentSum + i, TargetSum, i);
}
void ManyDiceSum(int howManyDice, int TargetSum) {
if (howManyDice > 0)
rep(howManyDice, "", 0, TargetSum, 1);
}

Algorithms - Circular Array Rotation

Is this linear complexity implementation of circular array rotation correct?
n = number of elements
k = number of rotations
int write_to = 0;
int copy_current = 0;
int copy_final = a[0];
int rotation = k;
int position = 0;
for (int i = 0; i < n; i++) {
write_to = (position + rotation) % n;
copy_current = a[write_to];
a[write_to] = copy_final;
position = write_to;
copy_final = copy_current;
}
No.
Consider this example.
#include <iostream>
int main(void) {
int n = 6;
int k = 2;
int a[] = {1, 2, 3, 4, 5, 6};
int write_to = 0;
int copy_current = 0;
int copy_final = a[0];
int rotation = k;
int position = 0;
for (int i = 0; i < n; i++) {
write_to = (position + rotation) % n;
copy_current = a[write_to];
a[write_to] = copy_final;
position = write_to;
copy_final = copy_current;
}
for (int i = 0; i < n; i++) {
std::cout << a[i] << (i + 1 < n ? ' ' : '\n');
}
return 0;
}
Expected result:
5 6 1 2 3 4
Actual result:
3 2 1 4 1 6
Using stl::rotate on std::array, you can left rotate by, say 2, as:
std::array<int, 6> a{1, 2, 3, 4, 5, 6};
std::rotate(begin(a), begin(a) + 2, end(a)); // left rotate by 2
to yield: 3 4 5 6 1 2, or right-rotate by, say 2, as:
std::rotate(begin(a), end(a) - 2, end(a)); // right rotate by 2
to yield: 5 6 1 2 3 4, with linear complexity.
Rotate an Array of length n for k times in left or right directions.
The code is in Java
I define a Direction Enum:
public enum Direction {
L, R
};
Rotation with times and direction:
public static final void rotate(int[] arr, int times, Direction direction) {
if (arr == null || times < 0) {
throw new IllegalArgumentException("The array must be non-null and the order must be non-negative");
}
int offset = arr.length - times % arr.length;
if (offset > 0) {
int[] copy = arr.clone();
for (int i = 0; i < arr.length; ++i) {
int j = (i + offset) % arr.length;
if (Direction.R.equals(direction)) {
arr[i] = copy[j];
} else {
arr[j] = copy[i];
}
}
}
}
Complexity: O(n).
Example:
Input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Rotate 3 times left
Output: [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]
Input: [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]
Rotate 3 times right
Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

C/C++ - efficient method of rotating an array without using build-in functions (homework)

The task is to rotate left or rotate right a subarray of an array given number of times.
Let me explain this on an example:
lets data be an array.
data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
a sub array is determined by parameters begin and end.
if begin = 3 and end = 7, then subarray is {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
if begin = 7 and end = 3, then subarray is {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
let's rotate it right two times
if begin = 3 and end = 7, then the result is {0, 1, 2, 6, 7, 3, 4, 5, 8, 9};
if begin = 7 and end = 3, then the result is {8, 9, 0, 1,, 4, 5, 6, 2, 3, 7};
I've written code that performs this task but it's to slow.
Can someone give me a hint how to make it quicker?
Important: I'm not allowed to use other arrays than data, subprograms and build-in functions.
#include <iostream>
using namespace std;
int main(){
int dataLength;
cin >> dataLength;
int data [ dataLength ];
for (int i = 0; i < dataLength; i++){
cin >> data [ i ];
}
int begin;
int end;
int rotation;
int forLoopLength;
int tempBefore;
int tempAfter;
cin >> begin;
cin >> end;
cin >> rotation;
if (end > begin)
forLoopLength = (end - begin) + 1;
else
forLoopLength = (end - begin) + 1 + dataLength;
if (rotation < 0)
rotation = forLoopLength + (rotation % forLoopLength);
else
rotation = rotation % forLoopLength;
for (int i = 0; i < rotation; i++) {
tempBefore = data [ end ];
for (int i = 0; i < forLoopLength; i++) {
tempAfter = data [ (begin + i) % dataLength ];
data [ (begin + i) % dataLength ] = tempBefore;
tempBefore = tempAfter;
}
}
for (int i = 0; i < dataLength; i ++ ) {
cout << data [ i ] << " ";
}
return 0;
}
There's a trick to this. It's pretty weird that you'd get this for homework if the trick wasn't mentioned in class. Anyway...
To rotate a sequence of N elements left by M:
reverse the whole sequence
reverse the last M elements
reverse the first N-M elements
done
e.g. left by 2:
1234567
->
7654321
->
7654312
->
3456712
Here is my code, it makes exactly n reads and n writes, where n is subarray size.
#include<iostream>
int arr[]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// replacing 'addr( pos, from, size )' with just 'pos' mean rotation the whole array
int addr( int ptr, int from, int size)
{
return (ptr + from ) % size;
}
void rotate( int* arr, int shift, int from, int count, int size)
{
int i;
int pos= 0;
int cycle= 0;
int c= 0;
int c_old= 0;
// exactly count steps
for ( i=0; i< count; i++ ){
// rotation of arrays part is essentially a permutation.
// every permutation can be decomposed on cycles
// here cycle processing begins
c= arr[ addr( pos, from, size ) ];
while (1){
// one step inside the cycle
pos= (pos + shift) % count;
if ( pos == cycle )
break;
c_old= c;
c= arr[ addr( pos, from, size ) ];
arr[ addr( pos, from, size ) ]= c_old;
i++;
}
// here cycle processing ends
arr[ addr( pos, from, size ) ]= c;
pos= (pos + 1) % count;
cycle= (cycle + 1) % count;
}
}
int main()
{
rotate( arr, 4, 6, 6, 11 );
int i;
for ( i=0; i<11; i++){
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return 0;
}

C++ Chocolate Puzzle [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Let's say I have N chocolates that have to be packed into exactly P boxes in the order they arrive. Each chocolate also has a number of calories X and each box has a capacity K which has to be less than or equal to 3*sum(x1, x2, ..., xn) + max(x1, x2, ..., xn)^2 - min(x1, x2, ..., xn)^2.
In the task I'm given N, P and X for each chocolate and I have to figure out the lowest possible K. Could anyone help me on this (not looking for a solution just for some hints regarding the problem)?
Example:
N = 8,
P = 3,
X = {1, 4, 5, 6, 3, 2, 5, 3}
K for first three chocolates = 3*(1+4+5) + 5^2 - 1^2 = 54
K for next two chocolates = 3*(6+3) + 6^2 - 3^2 = 54
K for last three chocolates = 3*(2+5+3) + 5^2 - 2^2 = 51
Lowest possible K = 54
So the goal is to find the best combination using exactly P boxes that has the lowest K.
Thanks!
Here is how I would solve this in Java:
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ChocolatePuzzle {
private static final Map <String, Integer> solutions =
new HashMap <String, Integer> ();
private static final Map <String, Integer> bestMoves =
new HashMap <String, Integer> ();
private static int [] x;
private static int k (int from, int to)
{
int sum = x [from];
int max = x [from];
int min = x [from];
for (int i = from + 1; i < to; i++)
{
sum += x [i];
max = Math.max (max, x [i]);
min = Math.min (min, x [i]);
}
return sum * 3 + max * max - min * min;
}
public static int solve (int n, int p)
{
String signature = n + "," + p;
Integer solution = solutions.get (signature);
if (solution == null)
{
solution = Integer.valueOf (doSolve (n, p, signature));
solutions.put (signature, solution);
}
return solution.intValue ();
}
public static int doSolve (int n, int p, String signature)
{
if (p == 1)
{
bestMoves.put (signature, Integer.valueOf (x.length - n));
return k (n, x.length);
}
else
{
int result = Integer.MAX_VALUE;
int bestMove = 0;
int maxI = x.length - n - p + 1;
for (int i = 1; i <= maxI; i++)
{
int k = Math.max (k (n, n + i), solve (n + i, p - 1));
if (k < result)
{
result = k;
bestMove = i;
}
}
bestMoves.put (signature, Integer.valueOf (bestMove));
return result;
}
}
public static void main(String[] args) {
int n = 20;
int p = 5;
x = new int [n];
Random r = new Random ();
for (int i = 0; i < n; i++)
x [i] = r.nextInt (9) + 1;
System.out.println("N: " + n);
System.out.println("P: " + p);
System.out.print("X: {");
for (int i = 0; i < n; i++)
{
if (i > 0) System.out.print (", ");
System.out.print (x [i]);
}
System.out.println("}");
System.out.println();
int k = solve (0, p);
int o = 0;
for (int i = p; i > 0; i--)
{
int m = bestMoves.get (o + "," + i);
System.out.print ("{");
for (int j = 0; j < m; j++)
{
if (j > 0)
System.out.print (", ");
System.out.print (x [o + j]);
}
System.out.print ("} (k: ");
System.out.print(k (o, o + m));
System.out.println (")");
o += m;
}
System.out.println("min(k): " + k);
}
}
Probably you could find some useful tips in this code.
Sample input:
N: 20
P: 5
X: {1, 7, 6, 6, 5, 5, 7, 9, 1, 3, 9, 5, 3, 7, 9, 1, 4, 2, 4, 8}
Sample output:
{1, 7, 6, 6} (k: 108)
{5, 5, 7, 9} (k: 134)
{1, 3, 9, 5} (k: 134)
{3, 7, 9} (k: 129)
{1, 4, 2, 4, 8} (k: 120)
min(k): 134

fastest algorithm count number of 3 length AP in array

I want to solve this CodeChef challenge:
Suppose We are given an array A of N(of range 100,000) elements. We are to find the count of all pairs of 3 such elements 1<=Ai,Aj,Ak<=30,000 such that
Aj-Ai = Ak- Aj and i < j < k
In other words Ai,Aj,Ak are in Arithmetic Progression. For instance for Array :
9 4 2 3 6 10 3 3 10
so The AP are:
{2,6,10},{9,6,3},{9,6,3},{3,3,3},{2,6,10}
So the required answer is 5.
My Approach
What I tried is take 30,000 long arrays named past and right. Initially right contains the count of each 1-30,000 element.
If we are at ith position past stores the count of array value before i and right stores the count of array after i. I simply loop for all possible common difference in the array. Here is the code :
right[arr[1]]--;
for(i=2;i<=n-1;i++)
{
past[arr[i-1]]++;
right[arr[i]]--;
k=30000 - arr[i];
if(arr[i] <= 15000)
k=arr[i];
for(d=1;d<=k;d++)
{
ans+= right[arr[i] + d]*past[arr[i]-d] + past[arr[i] + d]*right[arr[i]-d];
}
ans+=past[arr[i]]*right[arr[i]];
}
But this gets me Time Limit Exceeded. Please help with a better algorithm.
You can greatly cut execution time if you make a first pass over the list and only extract number pairs that it is possible to have an 3 term AP between (difference is 0 mod 2). And then iterating between such pairs.
Pseudo C++-y code:
// Contains information about each beginning point
struct BeginNode {
int value;
size_t offset;
SortedList<EndNode> ends; //sorted by EndNode.value
};
// Contains information about each class of end point
struct EndNode {
int value;
List<size_t> offsets; // will be sorted without effort due to how we collect offsets
};
struct Result {
size_t begin;
size_t middle;
size_t end;
};
SortedList<BeginNode> nodeList;
foreach (auto i : baseList) {
BeginNode begin;
node.value = i;
node.offset = i's offset; //you'll need to use old school for (i=0;etc;i++) with this
// baseList is the list between begin and end-2 (inclusive)
foreach (auto j : restList) {
// restList is the list between iterator i+2 and end (inclusive)
// we do not need to consider i+1, because not enough space for AP
if ((i-j)%2 == 0) { //if it's possible to have a 3 term AP between these two nodes
size_t listOffset = binarySearch(begin.ends);
if (listOffset is valid) {
begin.ends[listOffset].offsets.push_back(offsets);
} else {
EndNode end;
end.value = j;
end.offsets.push_back(j's offset);
begin.ends.sorted_insert(end);
}
}
}
if (begin has shit in it) {
nodeList.sorted_insert(begin);
}
}
// Collection done, now iterate over collection
List<Result> res;
foreach (auto node : nodeList) {
foreach (auto endNode : node.ends) {
foreach (value : sublist from node.offset until endNode.offsets.last()) {
if (value == average(node.value, endNode.value)) {
// binary_search here to determine how many offsets in "endNode.offsets" "value's offset" is less than.
do this that many times:
res.push_back({node.value, value, endNode.value});
}
}
}
}
return res;
Here's a simple C version of the solution that takes advantage of the Ai + Ak must be even test:
#include <stdio.h>
static int arr[] = {9, 4, 2, 3, 6, 10, 3, 3, 10};
int main ()
{
int i, j, k;
int sz = sizeof(arr)/sizeof(arr[0]);
int count = 0;
for (i = 0; i < sz - 2; i++)
{
for (k = i + 2; k < sz; k++)
{
int ik = arr[i] + arr[k];
int ikdb2 = ik / 2;
if ((ikdb2 * 2) == ik) // if ik is even
{
for (j = i + 1; j < k; j++)
{
if (arr[j] == ikdb2)
{
count += 1;
printf("{%d, %d, %d}\n", arr[i], arr[j], arr[k]);
}
}
}
}
}
printf("Count is: %d\n", count);
}
and the console dribble:
tmp e$ cc -o triples triples.c
tmp e$ ./triples
{9, 6, 3}
{9, 6, 3}
{2, 6, 10}
{2, 6, 10}
{3, 3, 3}
Count is: 5
tmp e$
This more complicated version keeps a list of Aj indexed by value to go from n-cubed to n-squared (kinda).
#include <stdio.h>
#include <stdint.h>
static uint32_t arr[] = {9, 4, 2, 3, 6, 10, 3, 3, 10};
#define MAX_VALUE 100000u
#define MAX_ASIZE 30000u
static uint16_t index[MAX_VALUE+1];
static uint16_t list[MAX_ASIZE+1];
static inline void remove_from_index (int subscript)
{
list[subscript] = 0u; // it is guaranteed to be the last element
uint32_t value = arr[subscript];
if (value <= MAX_VALUE && subscript == index[value])
{
index[value] = 0u; // list now empty
}
}
static inline void add_to_index (int subscript)
{
uint32_t value = arr[subscript];
if (value <= MAX_VALUE)
{
list[subscript] = index[value]; // cons
index[value] = subscript;
}
}
int main ()
{
int i, k;
int sz = sizeof(arr)/sizeof(arr[0]);
int count = 0;
for (i = 0; i < sz - 2; i++)
{
for (k = i; k < sz; k++) remove_from_index(k);
for (k = i + 2; k < sz; k++)
{
uint32_t ik = arr[i] + arr[k];
uint32_t ikdb2 = ik / 2;
add_to_index(k-1); // A(k-1) is now a legal middle value
if ((ikdb2 * 2) == ik) // if ik is even
{
uint16_t rover = index[ikdb2];
while (rover != 0u)
{
count += 1;
printf("{%d, %d, %d}\n", arr[i], arr[rover], arr[k]);
rover = list[rover];
}
}
}
}
printf("Count is: %d\n", count);
}
and the dribble:
tmp e$ cc -o triples triples.c
tmp e$ ./triples
{9, 6, 3}
{9, 6, 3}
{2, 6, 10}
{2, 6, 10}
{3, 3, 3}
Count is: 5
tmp e$