I've been reading the cracking the coding interview book. I am a bit stuck on implementing the runner technique for weaving elements of a linked list. The book goes as follows:
"Suppose you had a linked list a1->a2....->an->b1->b2....bn, and you want to rearrange it into a1->b1->a2->b2->.....an->bn. You don't know the length of the linked list but all you know is that it is an even number.
You could have one pointer p1 (fast pointer) move every two elements for every one move that p2 makes. When p1 hits the end of the linked list, p2 will be at the endpoint. Then, move p1 back to the front and begin "weaving" the elements. On each iteration, p2 selects an element and inserts it after p1."
Now I understand the technique up to the point before weaving starts. So, right before weaving, we basically have (for n=4 elements)
p1 p2
a1->a2->b1->b2
Now, if I understand correctly, I have to move the element pointed to by p2 (i.e. b1) and insert it after p1, in other words
p1.next = p2
which would result in the following list (?)
a1->b1->b2
How does the algorithm proceed from here?
I found this question but it seems to suggest that the above step would result in
a1->b1->a2->b2
which I do not see how. I am probably missing something fundamental here.
If A1 -> A2 -> ... -> AN -> B1 -> B2 ... -> BN is your original linked list, after the first step you'll have P1 and P2 pointing at A1 and B1 respectively. Let's say AN points to null, this can be done easily in the first step.
At each iteration, do these steps:
temp1 = P1.next
temp2 = P2.next //1
P2.next = P1.next //2
P1.next = P2 //3
P1 = temp1
P2 = temp2 //4
Here are the changes at the four positions in the first iteration:
1:
P1 P2
⬍ ⬍
A1 → A2 → ... → AN B1 → B2 ... → BN
⬍ ⬍
temp1 temp2
2:
P1 .–––––––––––––––.
⬍ ↓ ↑
A1 → A2 → ... → AN B1 B2 ... → BN
⬍ ⬍ ⬍
temp1 P2 temp2
3:
P1 .–––––––––––––––.
⬍ ↓ ↑
A1 A2 → ... → AN B1 B2 ... → BN //P2 points on B1
↓ ⬍ ↑ ⬍
↓ temp1 ↑ temp2
·––––––––––––––––––––·
This is equivalent to:
P1 P2
⬍ ⬍
A1 → B1 → A2 → ... → AN B2 ... → BN
⬍ ⬍
temp1 temp2
4:
P1 P2
⬍ ⬍
A1 → B1 → A2 → ... → AN B2 ... → BN
⬍ ⬍
temp1 temp2
And you repeat the same until P1 reaches AN.
The algorithms presented by Adam Stelmaszczyk, Igor Tandetnik and four_lines are correct; one only has to take care with the terminating condition otherwise the final nullptr that terminates the list can become lost. four_lines advocates handling this before doing the weaving. Or it can be done during the weaving by checking:
#include "stdafx.h"
#include <iostream>
namespace
{
struct elem
{
int val;
elem* next;
elem() : val(-1), next(nullptr) {}
};
}
int main()
{
// setup single-linked list of elements (an array here makes it easy...)
const int SIZE = 12; // even number
elem elems[SIZE];
for (int x = 0; x < SIZE - 1; ++x) { elems[x].next = &elems[x + 1]; }
for (int x = 0; x < SIZE; ++x) { elems[x].val = x; }
// divide the list using ptrs pf, ps to point at first part, second part
elem* pf = elems;
elem* ps = elems;
do
{
pf = pf->next;
pf = pf->next;
ps = ps->next;
} while (pf != nullptr);
pf = elems; // move pf back to start
// weave first and second parts of list using pf and ps
do
{
// update pf element next-ptr to point at ps, then move pf to its original next element
elem* oldpfnext = pf->next;
pf->next = ps;
pf = oldpfnext;
// if ps element is not at end, update ps element next-ptr to point the new location of pf
elem* oldpsnext = ps->next;
if (nullptr != ps->next)
{
ps->next = pf;
}
// now move ps to its original next element (even if null)...
ps = oldpsnext;
} while (nullptr != ps); // ... and stop if we are now at end
return 0;
}
Related
Code Source - https://github.com/Bibeknam/algorithmtutorprograms/blob/master/data-structures/red-black-trees/RedBlackTree.cpp
y = z;
int y_original_color = y->color;
if (z->left == TNULL) {
x = z->right;
rbTransplant(z, z->right);
} else if (z->right == TNULL) {
x = z->left;
rbTransplant(z, z->left);
} else {
y = minimum(z->right);
y_original_color = y->color;
x = y->right;
if (y->parent == z) {
x->parent = y; \\ [1] Local Class TNull
} else {
rbTransplant(y, y->right); \\ [2] Losing Y
y->right = z->right;
y->right->parent = y;
}
rbTransplant(z, y);
y->left = z->left;
y->left->parent = y;
y->color = z->color; \\ [3] Need of Recoloring
}
Questions
Local Class TNull - (In case y->right is a TNull) Within this class function, TNull is a local pointer simply passed to x; isn't changing the parent of x also change the parent of the local TNull?
Losing Y - This section is meant to be executed in case the minimum in right subtree of z is not a direct children. Later it will be placed at z's location. Won't this segment only pivot y->right / x until it reaches z's location, instead of y / minimum?
Need of Recoloring - Iirc, recoloring will also happen in the later fixDelete() function call, why is this needed?
Please bear with me, I'm slow in this kind of stuff and I'm really at my wits' end. This is the first time I'm asking here. Thank you.
On your questions
Yes that can happen, TNull's parent is set and the authors remark that this is a deliberate design choice which they exploit.
y is moving to where z is and this just fixes y so its pointers are what z had. s
No. Essentially when the node to be deleted has 2 children, you find the successor or predecessor node (which has to have 0 or 1 child) and swap the nodes. You then delete the node at the successor or predecessor node position. The predecessor or successor node swapped, preserves the tree ordering. But the important thing is in swapping the nodes, the colour is not swapped, it must be preserved so the red-black tree properties are still correct.
This is what y_original_color is for.
The following code causes a crash in my program, because
void fractalizeSegment() {
// Assume next != NULL
double deltaX = next->x - x;
double deltaY = next->y - y;
// Add 3 new points labeled a1, a2, a3 from this to next
Point a3(x + 2.0*deltaX/3.0, y + 2.0*deltaY/3.0, next);
double sqr3 = std::sqrt(3.0);
Point a2(x + deltaX/2.0 - sqr3*deltaY/2.0,
y + deltaY/2.0 + sqr3*deltaX/2.0,
&a3);
Point a1(x + deltaX/3.0, y + deltaY/3.0, &a2);
next = &a1;
}
Is somehow optimized to
void fractalizeSegment() {
next = &a1;
}
The method is called on p0 = {x = 0, y = 0, next = 0x7fffffffe100},
which point to p1 = {x = 1, y = 0, next = 0x0}.
By analyzing the program in the debugger I found that when I'm in the method fractalizeSegment:
a1 = {x = 6.9533558075099091e-310, y = 6.9533558075098597e-310, next = 0x7fffffffe190}
In address a1.next there is
a2 = {x = 6.9533558074508189e-310, y = 4.9406564584124654e-324, next = 0x34}.
Trying to deference (*a2.next).next causes a segmentation fault.
Why does g++ optimize my code like this? How can I prevent it?
The current workaround I found was printing out the values of a1, a2, and a3,
this prevented the optimization.
a1 is a local automatic variable that will be destroyed upon returning from the function, so any use of *next after that will be undefined. The compiler thinks that surely you will not use those values so why bother computing them.
You probably want to create a1 in the heap:
next = new Point(x + deltaX/3.0, y + deltaY/3.0, &a2); //no need of a1.
Maybe also a2 and a3 should be dynamically allocated, but that depends on the implementation of Point, that you did not show.
And remember to delete the allocated objects somewhere.
i have class name DPPoint what happens when we calculate this-(object of DPPoint) in same class and assign value to a variable of type int
If I understand correctly the question is about this:
DPPoint* p1 = new DPPoint;
DPPoint* p2 = new DPPoint;
int k = p1 - p2; // what is k?
That's perfectly valid code. It's called "pointer arithmetic". It will give you distance between p1 and p2 in sizes of DPPoint.
DPPoint array [10];
int k = &array[5] - &array[3]; // k = 2
int n = (int)&array[5] - (int)&array[3]; // n = 2 * sizeof (DPPoint)
(&array[5] == &array[3] + 2); // true
(&array[5] == array + 5); // also true
The pointers don't have to be in the same array. Can be two random addresses in memory (skipping alignment issues for simplicity).
I can quite easily calculate the point of intersection given two lines. If I start with two vertices:
(x1,y1)
(x2,y2)
I can calculate the slope by doing (y1-y2)/(x1-x2), and then calculating the intercept
y1 - slope * x1
Then do that again, so I have to sets of slope and intercept, then just do:
x = (intercept2 - intercept1) / (slope1 - slope2)
y = slope1 * x + intercept1
(disclaimer: this might not even work, but i've gotten something very close to it to work, and it illustrates my general technique)
BUT that only works with data types with decimals, or non integral. Say the vertices are:
(0,1)
(10,2)
To calculate the slope would result in (1-2)/(0-10), which is -1/-10 which is not 1/10, it is 0.
How can I get code that yields a valid result using only integers?
Edit: I can't use floats AT ALL!. No casting, no nothing. Also, values are capped at 65535. And everything is unsigned.
In high school when subtracting fractions, our teachers taught us to find a common denominator
So 1/4 - 1/6 = 3/12 - 2/12 = 1/12
So do the same with your slopes.
int slope1 = n1 / d1; // numerator / denominator
int slope2 = n2 / d2;
// All divisions below should have 0 for remainder
int g = gcd( d1, d2 ); // gcd( 4, 6 ) = 2
int d = d1 * d2 / g; // common denominator (12 above)
int n = (d/d1) * n1 - (d/d2) * n2; // (1 in 1/12 above)
// n1/d1 - n2/d2 == n/d
I hope I got that right.
Hm..
(0,1)
(10,2)
and (y1-y2)/(x1-x2). Well, this is the description of one line, not the intersection of two lines.
As far as I remember lines are described in the form of x * v with x an skalar and v be a vector. Then it's
x * (0,1) = v2 and
x * (10, 2) = v2.
therefore the lines only intersect if exactly one solution to both equitions exist, overlap when there are infinitive numbers of solutions and don't intersect when they are parallel.
http://www.gamedev.net/topic/647810-intersection-point-of-two-vectors/
explains the calcuclation based on the dot - product.
Input: line L passing thru (x1, y1) and (x2, y2), and line M passing thru (X1, Y1) and (X2, Y2)
Output: (x, y) of the intersecting point of two lines L and M
Tell Wolfram Alpha to solve y = (y1-y2)/(x1-x2)*(x-x1)+y1 and y = (Y1-Y2)/(X1-X2)*(x-X1)+Y1 for x, y to get this solution:
http://www.wolframalpha.com/share/clip?f=d41d8cd98f00b204e9800998ecf8427e3at5u9evl8
But I have no idea on how to write a program to implement the above solution for your calculator with only uint16_t ALU.
Thanks to Graham Toal's answer, below is a primitive Rust implementation of the linked C code in their answer, modified to return the point of intersection for the complete line, as opposed to the line segment. It doesn't use much Rust-specific magic so should be reasonably easy to port to other languages.
The function returns a Point where the Lines intersect, if at all, and a flag denoting whether the intersection point lies on both intersected lines (true) or not (false).
/// 2D integer point
struct Point {
/// The x coordinate.
pub x: i32,
/// The y coordinate.
pub y: i32,
}
/// Line primitive
struct Line {
/// Start point
pub start: Point,
/// End point
pub end: Point,
}
/// Check signs of two signed numbers
///
/// Fastest ASM output compared to other methods. See: https://godbolt.org/z/zVx9cD
fn same_signs(a: i32, b: i32) -> bool {
a ^ b >= 0
}
/// Integer-only line segment intersection
///
/// If the point lies on both line segments, the second tuple argument will return `true`.
///
/// Inspired from https://stackoverflow.com/a/61485959/383609, which links to
/// https://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsii/xlines.c
fn intersection(l1: &Line, l2: &Line) -> Option<(Point, bool)> {
let Point { x: x1, y: y1 } = l1.start;
let Point { x: x2, y: y2 } = l1.end;
let Point { x: x3, y: y3 } = l2.start;
let Point { x: x4, y: y4 } = l2.end;
// First line coefficients where "a1 x + b1 y + c1 = 0"
let a1 = y2 - y1;
let b1 = x1 - x2;
let c1 = x2 * y1 - x1 * y2;
// Second line coefficients
let a2 = y4 - y3;
let b2 = x3 - x4;
let c2 = x4 * y3 - x3 * y4;
let denom = a1 * b2 - a2 * b1;
// Lines are colinear
if denom == 0 {
return None;
}
// Compute sign values
let r3 = a1 * x3 + b1 * y3 + c1;
let r4 = a1 * x4 + b1 * y4 + c1;
// Sign values for second line
let r1 = a2 * x1 + b2 * y1 + c2;
let r2 = a2 * x2 + b2 * y2 + c2;
// Flag denoting whether intersection point is on passed line segments. If this is false,
// the intersection occurs somewhere along the two mathematical, infinite lines instead.
//
// Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1, the
// line segments do not intersect.
//
// Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line
// segment, the line segments do not intersect.
let is_on_segments = (r3 != 0 && r4 != 0 && same_signs(r3, r4))
|| (r1 != 0 && r2 != 0 && same_signs(r1, r2));
// If we got here, line segments intersect. Compute intersection point using method similar
// to that described here: http://paulbourke.net/geometry/pointlineplane/#i2l
// The denom/2 is to get rounding instead of truncating. It is added or subtracted to the
// numerator, depending upon the sign of the numerator.
let offset = if denom < 0 { -denom / 2 } else { denom / 2 };
let num = b1 * c2 - b2 * c1;
let x = if num < 0 { num - offset } else { num + offset } / denom;
let num = a2 * c1 - a1 * c2;
let y = if num < 0 { num - offset } else { num + offset } / denom;
Some((Point::new(x, y), is_on_segments))
}
I am trying to simulate 5 stage of pipeline. I have saved all the instruction into a struct.
( basically done with the stage of lixcal analysis )
eg:
ADD R1 R2 R3 // R1 = R2+ R3 ... struct pipe{ int pc, string instruction , int r1, int r2....}
now if p[i] is one of the stage of pipeline and ( p[1] could be pc=pc+1;
I[i] is instructions, ( I[1] could be ADD R1 R2 R3 )
what I want to do is
at t=1 : p[1] = I[1]
at t=2 :p[2] = I[1], p[1] = I[2]
at t=3 :p[3] = I[1], p[2] = I[2], p[1] = I[3]
at t=4 :p[4] = I[1], p[3] = I[2], p[2] = I[3], p[1] = I[4]
... and goes like that
I am using c++ so far. how could any one represent this cycle in c++ ?
It looks like you just want to add an element at the front of the array at each timestep, thus moving the already existant array elements one to the right. You could avoid doing O(n**2) ops like this
int& p_at_time(int index, int time_moment) {
return &p[time_moment-index+1];
}
and at t=1: p_at_time(1,1) = I[1];
at t=2: p_at_time(1,2) = I[2], (p_at_time(2,2) is already == I[1])
at t=3: p_at_time(1,3) = I[3], (p_at_time(2,3) and p_at_time(3,3) have the values I[2]
and I[1] respectively)