Ribbon shape using for loop in C++ - c++

I've been trying all day creating different for loop combinations in c++ and I can't seem to get the right one.
I want my output to look like this:
Ribbon
How can you display this without using arrays?
EDIT: I tried like this but I can't replicate it on the opposite end. This has been so far the closest output I've got.
for(int i = 0; i < 6; i++)
{
cout<<"*";
for(int j = 5; j > i; j--)
{
cout<<" ";
}
for(int k = 0; k <= i; k++)
{
cout<<"*";
}
cout<<endl;
}
OUTPUT:
Fail ribbon

You have nine lines; let's number them 0 to 8. Line number n contains:
1 + (4 - abs(4 - n)) asterisks (1, 2, 3, 4, 5, 4, 3, 2, 1)
2 * abs (4 - n) spaces (8, 6, 4, 2, 0, 2, 4, 6, 8)
1 + (4 - abs(4 - n)) asterisks (1, 2, 3, 4, 5, 4, 3, 2, 1)

One option is to increment the number of stars on each row, then go back down once you reached the midpoint.
void printChar(char c, int count)
{
for (int i = 0; i < count; i++)
std::cout << c;
}
int main()
{
const int len = 10;
int stars = 0;
while (++stars <= len / 2)
{
int spaces = len - stars * 2;
printChar('*', stars);
printChar(' ', spaces);
printChar('*', stars);
std::cout << "\n";
}
stars--;
while (--stars > 0)
{
int spaces = len - stars * 2;
printChar('*', stars);
printChar(' ', spaces);
printChar('*', stars);
std::cout << "\n";
}
return 0;
}

Related

How to make the difference between the values of an array as minimal as possible?

Given an array A of integers N, and after inputting the integers into the array, I need to make the difference between the neighboring less or equal to D and we need to do that in minimal moves. In the end print out the sum of the numbers that have been added or subtracted.
For every 0 < i < N, |S[i] - S[i - 1]| <= D
You can increase and decrease the number of the array element
Example 1: If we have an array like this
N = 7, D = 3 [2, 10, 2, 6, 4, 3, 3], then in this array we have to make the difference between the neighboring elements less or equal than 3. We don't modify the first array element, we skip over to the second array elements where we modify it from 10 down to 5 (since A[0] + 3 = 5), then we don't change the third element, we change the fourth element from 6 down to 5 (because A[3] + 3 = 5) and we don't change the rest of the elements because the difference between them is less than D. In the end we have to print out 6 (s = 0; 10 -> 5, s = 5; 6 -> 5, s = 6)
Example 2: If we have an array like this
N = 7, D = 0 [1, 4, 1, 2, 4, 2, 2]. Since D in this case is 0, by some logic we have to make all of the numbers the same. The most optimal (and in the fewest steps to solve this) way is we start with the last elements, we leave A[6] and A[5], we skip over to A[4]. Since A[4] is 4 and A[5] is 2, we have to change the 4 down to 2. Now since A[4] is 2, we skip over A[3] and we go to A[3] we change it from 1 up to 2. Then we change A[1] from 4 down to 2 and in the end, we change A[0] from 1 up to 2. In the end we have to print out 6 (s = 0; 4 -> 2, s = 2; 1 -> 2, s = 3; 4 -> 2, s = 5; 1 -> 2, s = 6).
Some other test cases:
N = 7, D = 1 [2, 10, 0, 2, 4, 3, 3] Solution: 10
N = 5, D = 1 [6, 5, 4, 3, 2] Solution: 0
I am unable to find an algorithm or an approach to this problem. I have tried several solutions and the closest I have come to solving it was 7/30 test cases.
My code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
int n, d, s1 = 0, s2 = 1;
cin >> n >> d;
int a[n], b[n];
for(int i = 0; i < n; i++) {
cin >> a[i];
b[i] = a[i];
}
reverse(b, b + n);
for(int i = 1; i < n; i++) {
if(a[i] - a[i - 1] <= d) {
continue;
} else {
if(a[i] > a[i - 1] + d) {
while(a[i] > a[i - 1] + d) {
a[i]--;
s1++;
}
} else if(a[i - 1] - d > a[i]) {
while(a[i - 1] - d > a[i]) {
a[i]++;
s1++;
}
}
}
}
for(int i = 1; i < n; i++) {
if(b[i] - b[i - 1] <= d) {
continue;
} else {
if(b[i] > b[i - 1] + d) {
while(b[i] > b[i - 1] + d) {
b[i]--;
s2++;
}
} else if(b[i - 1] - d > b[i]) {
while(b[i - 1] - d > b[i]) {
b[i]++;
s2++;
}
}
}
}
if(s1 >= s2)
cout << s2;
else
cout << s1;
return 0;
}

Is there a way to sort a vector in segments?

If I have a vector with an odd number of elements and want to sort the vector in segments, how could I construct a loop that does this but doesn't access anything out of bounds?
Like an array like this:
[4, 5, 6, 3, 10, 2, 0] (size: 7)
And I want to sort in segments of 2, so it becomes like this:
[4, 5, 3, 6, 2, 10, 0]
I was thinking something like this, but then the vector would access arr[8] which is out of bounds.
for(int i = 0; i < arr.size(); i = i + 2) {
sort(arr.begin() + i, arr.begin() + i - 1);
}
Two options spring to mind:
First, you can constrain your loop:
const int SegmentLen = 2;
for (int i=0; i+SegmentLen-1 < arr.size(); i += SegmentLen)
std::sort(arr.begin()+i, arr.begin()+i+SegmentLen);
Second, you can loop a fixed number of times:
auto segments = arr.size() / SegmentLen;
for (int i=0; i < segments; ++i)
std::sort(arr.begin() + (i*SegmentLen), arr.begin() + (i*SegmentLen) + SegmentLen);
//Handle any leftovers
Just get the first even number less than or equal to the size of the array and then use that as the stop condition for the loop.
int main(){
std::array<int, 7> arr = {4, 5, 6, 3, 10, 2, 0};
auto size = arr.size() % 2 ? arr.size() - 1 : arr.size(); // if odd subtract one else use size
for (size_t i = 0; i < size - 2; i += 2)
std::sort(arr.begin() + i, arr.begin() + i + 2);
for (auto e : arr)
std::cout << e << " ";
}
Outputs:
4 5 3 6 10 2 0

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]

Mixing two arrays by alternating elements two by two

What is an elegant algorithm to mix the elements two by two in two arrays (of potentially differing sizes) so that the items are drawn in an alternating fashion from each array, with the leftovers added to the end?
E.g.
Array 1: 0, 2, 4, 6
Array 2: 1, 3, 5, 7
Mixed array: 0, 2, 1, 3, 4, 6, 5, 7
Don't worry about null checking or any other edge cases, I'll handle those.
Here is my solution but it does not work properly:
for (i = 0; i < N; i++) {
arr[2 * i + 0] = A[i];
arr[2 * i + 1] = A[i+1];
arr[2 * i + 0] = B[i];
arr[2 * i + 1] = B[i+1];
}
It is very fiddly to calculate the array indices explicitly, especially if your arrays can be of different and possibly odd lengths. It is easier if you keep three separate indices, one for each array:
int pairwise(int c[], const int a[], size_t alen, const int b[], size_t blen)
{
size_t i = 0; // index into a
size_t j = 0; // index into b
size_t k = 0; // index into c
while (i < alen || j < blen) {
if (i < alen) c[k++] = a[i++];
if (i < alen) c[k++] = a[i++];
if (j < blen) c[k++] = b[j++];
if (j < blen) c[k++] = b[j++];
}
return k;
}
The returned value k will be equal to alen + blen, which is the implicit dimension of the result array c. Because the availability of a next item is checked for each array operation, this code works for arrays of different lengths and when the arrays have an odd number of elements.
You can use the code like this:
#define countof(x) (sizeof(x) / sizeof(*x))
int main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[] = {-1, -2, -3, -4, -5, -6};
int c[countof(a) + countof(b)];
int i, n;
n = pairwise(c, a, countof(a), b, countof(b));
for (i = 0; i < n; i++) {
if (i) printf(", ");
printf("%d", c[i]);
}
puts("");
return 0;
}
(The example is in C, not C++, but your code doesn't use any of C++'s containers such as vector, so I've uses plain old ´int` arrays with explicit dimensions, which are the same in C and C++.)
Some notes on the loop you have;
You use the same position in the result array arr to assign two values to it (one from A and one from B).
The calculation for the index is possibly more complex than it needs to be, consider using two indexers given the two ways you are indexing over the arrays.
I would propose you use a loop that has two indexers (i and j) and explicitly loop over the four elements of the result (i.e. two position for each input array). In each loop you increment the indexers appropriately (by 4 for the output array and by 2 for the input arrays).
#include <iostream>
int main()
{
using namespace std;
constexpr int N = 4;
int A[N] = {2, 4, 6, 8};
int B[N] = {1, 3, 5, 7};
int arr[N*2];
for (auto i = 0, j=0; i < N*2; i+=4, j+=2) {
arr[i + 0] = A[j];
arr[i + 1] = A[j+1];
arr[i + 2] = B[j];
arr[i + 3] = B[j+1];
}
for (auto i =0; i < N*2; ++i) {
cout << arr[i] << ",";
}
cout << endl;
}
Note: you mention you take care of corner cases, so the code here requires the input arrays to be of the same length and that the length is even.
Try this:
for (i = 0; i < N; i += 2) {
arr[2 * i + 0] = A[i];
arr[2 * i + 1] = A[i+1];
arr[2 * i + 2] = B[i];
arr[2 * i + 3] = B[i+1];
}
Didn't consider any corner case, just fixing your concept. For example, check whether any array index out of bound occurs or not. You can run live here.
it should like this.
for (i = 0; i < N; i+=2) {
arr[2 * i + 0] = A[i];
arr[2 * i + 1] = A[i+1];
arr[2 * i + 2] = B[i];
arr[2 * i + 3] = B[i+1];
}

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;
}