displayng number pyramid in O(n) execution - algorithm

How do we print the following with O(n) execution
may be using a single for loop?
1
2 3
4 5 n
up to n rows
all I can do is using nested for loops

Nested for loop doesn't necessarily mean it's not O(n) any more. If what's inside the nested loop gets executed O(n) times, then the nested loop is perfectly fine:
cur_num <- 1
cur_step <- 1
while cur_num <= n
for i <- 1 to cur_step
print cur_num++
cur_step++
print '\n'
With a single for loop, it's doable, but slightly less pleasant
cur_num <- 1
cur_step <- 1
cur_step_consumed <- 0
for i <- 1 to n
print cur_num++
cur_step_consumed++
if cur_step_consumed == cur_step
cur_step_consumed <- 0
cur_step++
print '\n'

In C++:
size_t amount = 1;
size_t count = 0;
for(size_t i=1;i<=n;++i){
cout << i << " ";
++count;
if (count == amount){
cout << endl;
count = 0;
++amount;
}
}
output for n = 29:
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29
The idea is to track the number of elements to print in the current row, and track the number of elements printed in the current row. When the number of elements we've printed for the current row is the same as the total number of elements to print for that row, reset the count and increment the number of elements to print for the next row. You can mess with the formatting to get prettier output, but this is the gist of how it can be done in O(n) time and O(1) space.

Related

last iteration gets skipped and not printed in a for loop

Im trying to build a code that when the user inputs a sequence of numbers it will go through the sequence comparing each numbers and for every new biggest number in the sequence it will sum all the previous ones
func main() {
var numeri []int
numeri = GetInputSlice()
fmt.Println(numeri)
var sum int
num := len(numeri)
for i := 0; i < num - 1 ; i++ {
sum += numeri[i]
if numeri[i] > numeri[i+1] || numeri[i] == num - 1 {
fmt.Println(sum)
sum = 0
}
}
}
full code over here: https://go.dev/play/p/13ljQPmKaRA
if I input this sequence of numbers [1 2 13 0 7 8 9 -1 0 2] I would like to get 16, 24 and 1.
But in my code I only get 16 and 24 without getting the last 1 and I can't figure out a way to fix this.
Only numeri[i] is ever added to sum, and your loop never visits the last item (i < num - 1), so how could the last item be ever added?
Range through the whole slice, perform the addition, but only compare to the next element if you're not at the last one. If we're at the last one, we also want to print, so we may use a single condition
i == max || numeri[i] > numeri[i+1]
Where the comparison to the next element will not be executed if i == max (short circuit evaluation).
For example:
max := len(numeri) - 1
for i, v := range numeri {
sum += v
if i == max || v > numeri[i+1] {
fmt.Println(sum)
sum = 0
}
}
This will output (try it on the Go Playground):
[1 2 13 0 7 8 9 -1 0 2]
16
24
1

Rotate Image - Java

I am doing a question where, given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. This my my code:
class Solution {
public void rotate(int[][] matrix) {
int size = matrix.length;
for(int i = 0 ; i < matrix.length; i++){
for(int y = 0 ; y < matrix[0].length ; y++){
matrix[i][y] = matrix[size - y - 1][i];
System.out.println(size - y - 1);
System.out.println(i);
System.out.println("");
}
}
}
}
This is the input and output results:
input matrix: [[1,2,3],[4,5,6],[7,8,9]]
output matrix: [[7,4,7],[8,5,4],[9,4,7]]
expected matrix: [[7,4,1],[8,5,2],[9,6,3]]
I do not really understand why I am getting duplicates in my output such as the number seven 3 times. On my System.out.println statement, I am getting the correct list of indexes :
2
0
1
0
0
0
2
1
1
1
0
1
2
2
What can be wrong?
I have found a solution. I will try my best to explain it.
Let us consider an array of size 4.
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now lets look at the numbers present only on the outside of the array:
1 2 3 4
5 8
9 12
13 14 15 16
We will proceed by storing the first element 1 in a temporary variable. Next we will replace 1 by 13, 13 by 16, 16 by 4 and at last 4 by 1 (whose value we already stored in the temporary variable).
We will do the same for all the elements of the first row.
Here is a pseudocode if you just want to rotate this outer ring, lets call it an outer ring:
for i = 0 to n-1
{
temp = A[0][i];
A[0][i] = A[n-1-i][0];
A[n-1-i][0] = A[n-1-0][n-1-i];
A[n-1-0][n-1-i] = A[i][n-1-0];
A[i][n-1-0] = temp;
}
The code runs for a total of n times. Once for each element of first row. Implement this code an run it. You will see only the outer ring is rotated. Now lets look at the inner ring:
6 7
10 11
Now the loop in pseudocode only needs to run for 2 times and also our range of indexes has decreased. For outer ring, the loop started from i = 0 and ended at i = n-1. However, for the inner ring the for loop need to run from i = 1 to i = n-2.
If you had an array of size n, to rotate the xth ring of the array, the loop needs to run from i = x to i = n-1-x.
Here is the code to rotate the entire array:
x = 0;
int temp;
while (x < n/2)
{
for (int i = x;i < n-1-x;i++)
{
temp = arr[x][i];
arr[x][i] = arr[n-1-i][x];
arr[n-1-i][x] = arr[n-1-x][n-1-i];
arr[n-1-x][n-1-i] = arr[i][n-1-x];
arr[i][n-1-x] = temp;
}
x++;
}
Here each value of x denotes the xth ring.
0 <= x <= n-1
The reason why the outer loop runs only for x < n/2 times is because each array has n/2 rings when n is even and n/2 + 1 rings if n is odd.
I hope I have helped you. Do comment if face any problems with the solution or its explanation.

Cyclomatic Complexity number - do I have to count every statement separately as node?

I came across different ways of calculating CCN (according to formula CCN = E-N+2P)
One way was to count all the lines in the code separately and the other way is to count a few lines of code as one step; lets have the following example:
1 public class SumAndAverage {
2
3 public static void main (String[] args) {
4 int sum = 0;
5 double average = 0.0;
6 String message = "";
7
8 int num = Integer.parseInt(args[0]);
9
10 if ((num < 1) || (num > 100)) {
11 message = "Invalid number entered.";
12 } else {
13 for (int i = 1; i <= num; i++) {
14 sum += i;
15 }
16 average = (double) sum / num;
17 message = "The sum is " + sum + " and the average is " + average;
18 }
19 System.out.println(message);
20 }
21}
Counting every statement we'd get 12 - 11 + 2x 1 = 3
I was wondering if I "join" lines 4,5,6,8 and count them as one step and do the same with line 16 and 17, would that be correct too? The result would be the same as no of edges would also decrease: 8 - 7 + 2*1 = 3
The right way to calculate complexity is by considering blocks of code. A block of code is where there is no chance of dissecting the execution path.
McCabe's paper mentions the below:
The tool, FLOW, was written in APL to input the source code from Fortran files on disk. FLOW would then break a Fortran job into distinct subroutines and analyze the control structure of each subroutine. It does this by breaking the Fortran subroutines into blocks that are delimited by statements that affect control flow: IF, GOTO ,referenced LABELS, DO, etc.
For other information on complexity, also read through Cyclomatic complexity as a Quality measure

awk skipping records. getline command

this is a task related to data compression using fibonacci binary representation.
what i have is this text file:
result.txt
a 20
b 18
c 18
d 15
e 7
this file is a result of scanning a text file and counting the appearances of each char on the file using awk.
now i need to give each char its fibonacci-binary representation length.
since i'm new to ubuntu and teminal, i've done a program in java that receives a number and prints all the fibonacci codewords length up to the number and it's working.
this is exactly what i'm trying to do here. the problem is that it doesn't work...
the length of fibonacci codewords is also work as fibonnaci.
these are the rules:
f(1)=1 - there is 1 codeword of length 1.
f(2)=1 - there is 1 codeword of length 2.
f(3)=2 - there is 2 codeword of length 3.
f(4)=3 - there is 3 codeword of length 4.
and so on...
(i'm adding on more bit to each codeword so the first two lengths will be 2 and 3)
this is the code i've made: its name is scr5
{
a=1;
b=1;
len=2
print $1 , $2, len;
getline;
print $1 ,$2, len+1;
getline;
len=4;
for(i=1; i< num; i++){
c= a+b;
g=c;
while (c >= 1){
print $1 ,$2, len ;
if (getline<=0){
print "EOF"
exit;
}
c--;
i++;
}
a=b;
b=c;
len++;
}}
now i write on terminal:
n=5
awk -v num=$n -f scr5 a
and there are two problems:
1. it skips the third letter c.
2. on the forth letter d, it prints the length of the first letter, 2, instead of length 3.
i guess that there is a problem in the getline command.
thank u very much!
Search Google for getline and awk and you'll mostly find reasons to avoid getline completely! Often it's a sign you're not really doing things the "awk" way. Find an awk tutorial and work through the basics and I'm sure you'll see quickly why your attempt using getlines is not getting you off in the right direction.
In the script below, the BEGIN block is run once at the beginning before any input is read, and then the next block is automatically run once for each line of input --- without any need for getline.
Good luck!
$ cat fib.awk
BEGIN { prior_count = 0; count = 1; len = 1; remaining = count; }
{
if (remaining == 0) {
temp = count;
count += prior_count;
prior_count = temp;
remaining = count;
++len;
}
print $1, $2, len;
--remaining;
}
$ cat fib.txt
a 20
b 18
c 18
d 15
e 7
f 0
g 0
h 0
i 0
j 0
k 0
l 0
m 0
$ awk -f fib.awk fib.txt
a 20 1
b 18 2
c 18 3
d 15 3
e 7 4
f 0 4
g 0 4
h 0 5
i 0 5
j 0 5
k 0 5
l 0 5
m 0 6
The above solution, compressed form :
mawk 'BEGIN{ ___= __= _^=____=+_ } !_ { __+=(\
____=___+_*(_=___+=____))^!_ } $++NF = (_--<_)+__' fib.txt
a 20 1
b 18 2
c 18 3
d 15 3
e 7 4
f 0 4
g 0 4
h 0 5
i 0 5
j 0 5
k 0 5
l 0 5
m 0 6

Need to find the next greater element of every element in an array [duplicate]

This question already has answers here:
Given an array, find out the next smaller element for each element
(13 answers)
Closed 8 years ago.
Description of Algorithm
For each element in the input array, the corresponding output is the first number that follows the input element, that is greater than the input element.
In other words, for a given input[i], the output[i] is some element input[j] where j is the minimum index such that j > i and input[j] > input[i]
Example
Input 12 15 22 9 7 2 18 23 27
Output 15 22 23 18 18 18 23 27 -1
For example, the output that corresponds to 9 is 18 since 18 is the first number in the array that meets these requirements
follows 9 in the input array
is greater than 9
Question
Can anyone suggest me an algorithm better than O(n^2)?
This can be done in O(N) time and O(N) extra memory space with the help of two stacks (one for indices and other for values).
I'll explain the algorithm with the help of your example.
Input 12 15 22 9 7 2 18 23 27
Initialize Output Array O[] as all -1.
1. Start from the first element. Set CurrentElement = A[0] (12). index = 0
2. Push A[index] in a Stack S_values. Push index in a Stack S_indices.
3. Increment index.
4. while ( S_values is not empty && A[index] is > than S_values.top() )
- Set output_index = S_indices.top()
- set O[output_index] = A[index].
- S_values.pop()
- S_indices.pop().
5. If index < length(Input)-1 Goto Step 2.
6. Set O[index] = -1. // Last element.
This works because the top of the stack S_values shall always have the lowest value and the elements shall be popped out from it in ascending order. Similarly the stack S_indices shall always have the largest value on top and indices shall be popped out in descending order.
EDIT: Code in C++
#include <vector>
#include <stack>
#include <iostream>
using std::cout;
using std::endl;
using std::vector;
using std::stack;
int main()
{
vector<int> Input = { 12, 15, 22, 9, 7, 2, 18, 23, 27};
vector<int> Output( Input.size(), -1 );
stack<int> S_values, S_indices;
S_values.push( Input[0] );
S_indices.push( 0 );
for ( size_t index = 1; index < Input.size(); ++index )
{
while ( !S_values.empty() && Input[index] > S_values.top() )
{
size_t output_index = S_indices.top();
Output[ output_index ] = Input[ index ];
S_values.pop();
S_indices.pop();
}
S_values.push( Input[index] );
S_indices.push( index );
}
for ( auto &x : Output )
cout << x << " ";
cout << endl;
return 0;
}
Output:
15 22 23 18 18 18 23 27 -1
One approach is to use a stack, where each entry in the stack is a value:index pair. Iterate through the input array, popping items from the stack whose value is less than the value of the current item in the input array. Once all of the smaller values have been popped from the stack, push the current value:index pair onto the stack. When the end of the input array is reached, any remaining entries in the stack get an output value of -1 to indicate that no larger number was found.
Using the example in the question, here's how the algorithm would work
input item 12
stack = 12:0
input item 15
pop 12:0 and set output[0] = 15
stack = 15:1
input item 22
pop 15:1 and set output[1] = 22
stack = 22:2
input item 9
stack = 9:3, 22:2
input item 7
stack = 7:4, 9:3, 22:2
input item 2
stack = 2:5, 7:4, 9:3, 22:2
input item 18
pop 2:5 and set output[5] = 18
pop 7:4 and set output[4] = 18
pop 9:3 and set output[3] = 18
stack = 18:6, 22:2
input item 23
pop 18:6 and set output[6] = 23
pop 22:2 and set output[2] = 23
stack = 23:7
input item 27
pop 23:7 set output[7]= 27
stack = 27:8
end of array
pop 27:8 and set output[8] = -1
done

Resources