skyline algorithm - c

How do I find the vertices of the broken line that surrounds the silhouette in this image?
A possible input for the example above is:
WIDTH HEIGHT POSITION
3 9 17
5 9 9
12 4 8
3 11 3
10 7 1
2 3 19
So for this example the solution would be
[(1, 0), (1, 7), (3, 7), (3, 11), (6, 11), (6, 7),
(9, 7), (9, 9), (14, 9), (14, 4), (17, 4), (17, 9),
(20, 9), (20, 3), (21, 3), (21, 0)]

This is pretty simple. Make an array that is the length of the X axis, initialize to 0. As you read in the inputs, write the heights into this array if the height is >= the current value at that location in the array.
Then just loop over the array, and every time the value changes it is a vertex.
Basically:
int heights[SIZE] = {0};
int i, width, pos, height, prev = -1;
while (scanf("%d %d %d", &width, &height, &pos) == 3) {
for (i = 0; i < width; ++i) {
if (heights[pos+i] < height)
heights[pos+i] = height;
}
}
for (i = 0; i < SIZE; ++i) {
if (heights[i] != prev) {
printf("(%d,%d) ", i+1, heights[i]);
prev = heights[i];
}
}
printf("\n");

In the naive case, this doesn't seem like a very difficult algorithm. Do you know if the input size will get large/how large?
My initial attempt: Try to move from left to right. First pick the block with the leftmost edge that exists on the origin line. Climb to its top. Find all blocks with a left edge between the current point and the upper right point of the current block. Of that set, pick the closest (but check for edge cases, pun not intended). If the set is empty, start working your way down the right side of the block, looking for other blocks you may intercept.
Basically this is just how you'd trace it with your eye.
You can do some simple optimization by keeping sorted lists and then searching the lists rather than finding sets and digging around. For example, you might keep 4 sorted lists of the blocks, each sorted by the x or y coordinate of one of the sides.
If you have many, many blocks, you could consider using a multi-dimensional data structure to further organize the information.

I solved this problem using the sweep-line algorithm. This is a python class solution.
there two keys:
1) using the variable "points" to save all the left and right points and their heights and the sign of the height to indicate whether the points are left or right.
2) the variable "active" is used to save all the active lines that has been scanned.
class Solution:
# #param {integer[][]} buildings
# #return {integer[][]}
def getSkyline(self, buildings):
if len(buildings)==0: return []
if len(buildings)==1: return [[buildings[0][0], buildings[0][2]], [buildings[0][1], 0]]
points=[]
for building in buildings:
points+=[[building[0],building[2]]]
points+=[[building[1],-building[2]]] # the negative sign means this point is a right point
points=sorted(points, key=lambda x: x[0])
moving, active, res, current=0, [0], [],-1
while moving<len(points):
i=moving
while i<=len(points):
if i<len(points) and points[i][0]==points[moving][0]:
if points[i][1]>0:
active+=[points[i][1]]
if points[i][1]>current:
current=points[i][1]
if len(res)>0 and res[-1][0]==points[i][0]:
res[-1][1]=current
else:
res+=[[points[moving][0], current]]
else:
active.remove(-points[i][1]) #remove height of the lines than have been finished with scanning
i+=1
else:
break
if max(active)<current:
current=max(active)
res+=[[points[moving][0], current]]
moving=i
return res

I made a Java class to try and solve this. The class includes methods for generating, solving and printing data-sets. I haven't tested extensively, there may be a few bugs remaining. Also, my solution may be needlessly complicated, but it's designed to work (in theory) for non-discrete height and coordinate values.
import java.util.Random;
public class Skyline {
private int[][] buildings;
private int[][] skyline;
private int maxLength;
private int maxHeight;
public Skyline(int buildings, int maxLength, int maxHeight) {
this.maxLength = maxLength;
this.maxHeight = maxHeight;
makeRandom(buildings);
}
public Skyline(int[][] buildings, int dimensions) {
this.maxLength = maxLength;
this.maxHeight = maxHeight;
this.buildings = buildings;
}
public void makeRandom(int buildings) {
this.buildings = new int[buildings][3];
Random rand = new Random();
for(int i = 0; i < buildings; i++) {
int start = rand.nextInt(maxLength-3);
int end = rand.nextInt(maxLength - start - 1) + start + 1;
int height = rand.nextInt(maxHeight-1) + 1;
this.buildings[i][0] = start;
this.buildings[i][1] = height;
this.buildings[i][2] = end;
}
boolean swapped = true;
while(swapped) {
swapped = false;
for(int i = 0; i < this.buildings.length-1; i++) {
if(this.buildings[i][0] > this.buildings[i+1][0]) {
swapped = true;
int[] temp = this.buildings[i];
this.buildings[i] = this.buildings[i+1];
this.buildings[i+1] = temp;
}
}
}
// this.buildings[0][0] = 2;
// this.buildings[0][1] = 3;
// this.buildings[0][2] = 8;
}
public void printBuildings() {
print(this.buildings, false);
}
public void printSkyline() {
print(this.buildings, true);
}
public void print(int[][] buildings, boolean outline) {
char[][] str = new char[this.maxLength][this.maxHeight];
for(int i = 0; i < this.maxLength; i++) {
for(int j = 0; j < this.maxHeight; j++) {
str[i][j] = '.';
}
}
for(int i = 0; i < buildings.length; i++) {
int start = buildings[i][0];
int height = buildings[i][1];
int end = buildings[i][2];
//print the starting vertical
for(int j = 0; j < height; j++) {
if(outline) str[start][j] = str[start][j] == '|' ? '.' : '|';
else str[start][j] = '|';
}
//print the ending vertical
for(int j = 0; j < height; j++) {
if(outline) str[end][j] = str[end][j] == '|' ? '.' : '|';
else str[end][j] = '|';
}
//print the horizontal
if(height > 0) {
for(int j = start; j <= end; j++) {
str[j][height] = str[j][height] == '|' ? '|' : '-';
}
}
}
for(int i = maxHeight-1; i >= 0; i--) {
for(int j = 0; j < maxLength; j++) {
System.out.print(str[j][i]);
}
System.out.println();
}
System.out.println();
}
public void solveSkyline() {
for(int i = 0; i < buildings.length; i++) {
boolean reduced = true;
while(reduced) {
reduced = false;
for(int j = i+1; j < buildings.length; j++) {
if(buildings[j][0] < buildings[i][2] && buildings[j][1] > buildings[i][1] && buildings[j][2] >= buildings[i][2]) { //if intersecting building is taller, and longer
buildings[i][2] = buildings[j][0];
reduced = true;
break;
} else if(buildings[j][0] < buildings[i][2] && buildings[j][1] <= buildings[i][1] && buildings[j][2] >= buildings[i][2]) { //intersecting building is shorter, but longer
buildings[j][0] = buildings[i][2];
reduced = true;
break;
} else if(buildings[j][0] < buildings[i][2] && buildings[j][1] > 0 && buildings[j][1] < buildings[i][1] && buildings[j][2] <= buildings[i][2]) { //building is invisible, so ignore it
buildings[j][1] = 0;
reduced = true;
break;
} else if(buildings[j][0] < buildings[i][2] && buildings[j][2] <= buildings[i][2] && buildings[j][1] > buildings[i][1]) {
int[] newBuilding = new int[]{buildings[j][2], buildings[i][1], buildings[i][2]};
int[][] newBuildings = new int[buildings.length+1][3];
boolean inserted = false;
buildings[i][2] = buildings[j][0];
for(int k = 0; k < buildings.length; k++) {
if(inserted == false) {
if(newBuilding[0] < buildings[k][0]) {
newBuildings[k] = newBuilding;
newBuildings[k+1] = buildings[k];
inserted = true;
} else {
newBuildings[k] = buildings[k];
}
}
if(inserted == false && k == buildings.length - 1) {
newBuildings[k+1] = newBuilding;
} else {
newBuildings[k+1] = buildings[k];
}
}
buildings = newBuildings;
reduced = true;
break;
}
}
}
}
}
public static void main(String args[]) {
Skyline s = new Skyline(5, 100, 10);
s.printBuildings();
s.solveSkyline();
s.printBuildings();
s.printSkyline();
}
}

My solution to the problem as described here https://leetcode.com/problems/the-skyline-problem/ it iterates the list of buildings twice, however this could be combined into a single iteration. However, there are more optimal approaches if you consider the pure algorithm solution explained here http://www.algorithmist.com/index.php/UVa_105
class Solution {
public:
vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
// The final result.
vector<pair<int, int>> result;
// To hold information about the buildings
std::set<BuildingInformation> buildingInformation;
// Go through each building, and store information about the start and end heights.
for ( vector<vector<int>>::iterator buildingIt = buildings.begin( ); buildingIt != buildings.end( ); ++buildingIt ) {
BuildingInformation buildingStart;
buildingStart.x = (*buildingIt)[0];
buildingStart.h = (*buildingIt)[2];
buildingStart.StartOrEnd = Start;
buildingInformation.insert(buildingStart);
buildingStart.x = (*buildingIt)[1];
buildingStart.StartOrEnd = End;
buildingInformation.insert(buildingStart);
}
// Keep track of the current height.
int currentHeight = 0;
// A map of active building heights against number of buildings (to handle multiple buildings overlapping with same height).
// As it is a map, it'll be sorted by key, which is the height.
std::map<int, int> heights;
// Go through each building information that we generated earlier.
for ( std::set<BuildingInformation>::iterator it = buildingInformation.begin( ); it != buildingInformation.end( ); ++it ) {
if ( it->StartOrEnd == Start ) {
// This is a start point, do we have this height already in our map?
if ( heights.find( it->h ) != heights.end( ) ) {
// Yes, increment count of active buildings with this height/
heights[ it->h ] += 1;
} else {
// Nope, add this building to our map.
heights[ it->h ] = 1;
}
// Check if building height is taller than current height.
if ( it->h > currentHeight ) {
// Update current height and add marker to results.
currentHeight = it->h;
result.push_back( pair<int, int>( it->x, currentHeight ) );
}
} else {
// This is an end point, get iterator into our heights map.
std::map<int, int>::iterator heightIt = heights.find( it->h );
// Reduce by one.
heightIt->second -= 1;
// If this was the last building of the current height in the map...
if ( heightIt->second == 0 ) {
// Remove from heights map.
heights.erase( heightIt );
// If our height was the current height...
if ( it->h == currentHeight ) {
// If we have no more active buildings...
if ( heights.size( ) == 0 ) {
// Current height is zero.
currentHeight = 0;
} else {
// Otherwise, get iterator to one past last.
heightIt = heights.end( );
// Go back to get last valid iterator.
--heightIt;
// Store current height.
currentHeight = heightIt->first;
}
// Add marker to results.
result.push_back( pair<int, int>( it->x, currentHeight ) );
}
}
}
}
return result;
}
private:
// Is this a building start or end?
enum BuildingStartOrEnd
{
Start = 0,
End
};
// Information about building, there are two of these for each building, one for start, one for end.
struct BuildingInformation
{
int x;
int h;
BuildingStartOrEnd StartOrEnd;
// The ordering algorithm for the key, the rules we want to implement is keys are put in X order, and
// in the case of a tie (x values the same), we want Start pieces to come before End pieces (this is
// to handle cases where an old building ends and a new building begins on same X index, in which case
// we want to process the new start before processing the old end), however if we have two Start pieces
// at the same index, we wish to favour taller pieces (in this scenario we want to add a marker for the
// tallest building), finally if we have two End pieces at the same index, we wish to prefer lower
// pieces, as when multiple buildings end, we only want to add one result for the ultimate lowest point.
bool operator < ( const BuildingInformation & rhs ) const
{
if ( x == rhs.x )
{
if ( StartOrEnd == rhs.StartOrEnd ) {
if ( StartOrEnd == Start )
return h > rhs.h;
else
return h < rhs.h;
} else {
return StartOrEnd < rhs.StartOrEnd;
}
}
return x < rhs.x;
}
};
};

Related

Given a list of numbers and a number k, return whether any two numbers from the list add up to k

This question was asked in the Google programming interview. I thought of two approaches for the same:
Find all the subsequences of length. While doing so compute the sum and of the two elements and check if it is equal to k. If ye, print Yes, else keep searching. This is a brute Force approach.
Sort the array in non-decreasing order. Then start traversing the array from its right end. Say we have the sorted array, {3,5,7,10} and we want the sum to be 17. We will start from element 10, index=3, let's denote the index with 'j'. Then include the current element and compute required_sum= sum - current_element. After that, we can perform a binary or ternary search in array[0- (j-1)] to find if there is an element whose value is equal to the required_sum. If we find such an element, we can break as we have found a subsequence of length 2 whose sum is the given sum. If we don't find any such element, then decrease the index of j and repeat the above-mentioned steps for resulting subarray of length= length-1 i.e. by excluding the element at index 3 in this case.
Here we have considered that array could have negative as well as positive integers.
Can you suggest a better solution than this? A DP solution maybe? A solution that can further reduce it's time complexity.
This question can be easily solved with the help of set in O(N) time and space complexity.First add all the elements of array into set and then traverse each element of array and check whether K-ar[i] is present in set or not.
Here is the code in java with O(N) complexity :
boolean flag=false;
HashSet<Long> hashSet = new HashSet<>();
for(int i=0;i<n;i++){
if(hashSet.contains(k-ar[i]))flag=true;
hashSet.add(ar[i]);
}
if(flag)out.println("YES PRESENT");
else out.println("NOT PRESENT");
Here is a Java implementation with the same time complexity as the algorithm used to sort the array. Note that this is faster than your second idea because we do not need to search the entire array for a matching partner each time we examine a number.
public static boolean containsPairWithSum(int[] a, int x) {
Arrays.sort(a);
for (int i = 0, j = a.length - 1; i < j;) {
int sum = a[i] + a[j];
if (sum < x)
i++;
else if (sum > x)
j--;
else
return true;
}
return false;
}
Proof by induction:
Let a[0,n] be an array of length n+1 and p = (p1, p2) where p1, p2 are integers and p1 <= p2 (w.l.o.g.). Assume a[0,n] contains p1 and p2. In the case that it does not, the algorithm is obviously correct.
Base case (i = 0, j = n):
a[0,-1] does not contain p1 and a[n,n+1] does not contain p2.
Hypothesis:
a[0,i-1] does not contain a[i] and a[j+1,n] does not contain p2.
Step case (i to i + 1 or j to j - 1):
Assume p1 = a[i]. Then, since p1 + a[j] < p1 + p2, index j must be increased. But from the hypothesis we know that a[j+1,n-1] does not contain p2. Contradiction. It follows that p1 != a[i].
j to j - 1 analogously.
Because each iteration, a[0,i-1] and a[j+1,n], does not contain p1, and p2, a[i,j] does contain p1 and p2. Eventually, a[i] = p1 and a[j] = p2 and the algorithm returns true.
This is java implementation with O(n) Time complexity and O(n) space. The idea is have a HashMap which will contain complements of every array element w.r.t target. If the complement is found, we have 2 array elements which sum to the target.
public boolean twoSum(int[] nums, int target) {
if(nums.length == 0 || nums == null) return false;
Map<Integer, Integer> complementMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int curr = nums[i];
if(complementMap.containsKey(target - curr)){
return true;
}
complementMap.put(curr, i);
}
return false;
}
if you want to find pair count,
pairs = [3,5,7,10]
k = 17
counter = 0
for i in pairs:
if k - i in pairs:
counter += 1
print(counter//2)
Python Solution:
def FindPairs(arr, k):
for i in range(0, len(arr)):
if k - arr[i] in arr:
return True
return False
A = [1, 4, 45, 6, 10, 8]
n = 100
print(FindPairs(A, n))
Or
def findpair(list1, k):
for i in range(0, len(list1)):
for j in range(0, len(list1)):
if k == list1[i] + list1[j]:
return True
return False
nums = [10, 5, 6, 7, 3]
k = 100
print(findpair(nums, k))
Here is python's implementation
arr=[3,5,7,10]
k=17
flag=False
hashset = set()
for i in range(0,len(arr)):
if k-arr[i] in hashset:
flag=True
hashset.add(arr[i])
print( flag )
Javascript solution:
function hasSumK(arr, k) {
hashMap = {};
for (let value of arr) {
if (hashMap[value]) { return true;} else { hashMap[k - value] = true };
}
return false;
}
Using Scala, in a single pass with O(n) time and space complexity.
import collection.mutable.HashMap
def addUpToK(arr: Array[Int], k: Int): Option[Int] = {
val arrayHelper = new HashMap[Int,Int]()
def addUpToKHelper( i: Int): Option[Int] = {
if(i < arr.length){
if(arrayHelper contains k-arr(i) ){
Some(arr(i))
}else{
arrayHelper += (arr(i) -> (k-arr(i)) )
addUpToKHelper( i+1)
}
}else{
None
}
}
addUpToKHelper(0)
}
addUpToK(Array(10, 15, 3, 7), 17)
C++ solution:
int main(){
int n;
cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
int k;
cin>>k;
int t = false;
for(int i = 0; i < n-1; i++)
{
int s = k-arr[i];
for(int j = i+1; j < n; j++)
{
if(s==arr[j])
t=true;
}
}
if (t){
cout<<"Thank you C++, very cool";
}
else{
cout<<"Damn it!";
}
return 0;
}
Python code:
L = list(map(int,input("Enter List: ").split()))
k = int(input("Enter value: "))
for i in L:
if (k - i) in L:
print("True",k-i,i)
Here is Swift solution:
func checkTwoSum(array: [Int], k: Int) -> Bool {
var foundPair = false
for n in array {
if array.contains(k - n) {
foundPair = true
break
} else {
foundPair = false
}
}
return foundPair
}
def sum_total(list, total):
dict = {}
for i in lista:
if (total - i) in dict:
return True
else:
dict[i] = i
return False
Here is a C implementationFor Sorting O(n2) time and space complexity.For Solving Problem We use
single pass with O(n) time and space complexity via Recursion.
/* Given a list of numbers and a number k , return weather any two numbers from the list add up to k.
For example, given [10,15,3,7] and k of 17 , return 10 + 7 is 17
Bonus: Can You Do in one pass ? */
#include<stdio.h>
int rec(int i , int j ,int k , int n,int array[])
{
int sum;
for( i = 0 ; i<j ;)
{
sum = array[i] + array[j];
if( sum > k)
{
j--;
}else if( sum < k)
{
i++;
}else if( sum == k )
{
printf("Value equal to sum of array[%d] = %d and array[%d] = %d",i,array[i],j,array[j]);
return 1;//True
}
}
return 0;//False
}
int main()
{
int n ;
printf("Enter The Value of Number of Arrays = ");
scanf("%d",&n);
int array[n],i,j,k,x;
printf("Enter the Number Which you Want to search in addition of Two Number = ");
scanf("%d",&x);
printf("Enter The Value of Array \n");
for( i = 0 ; i <=n-1;i++)
{
printf("Array[%d] = ",i);
scanf("%d",&array[i]);
}
//Sorting of Array
for( i = 0 ; i <=n-1;i++)
{
for( j = 0 ; j <=n-i-1;j++)
{
if( array[j]>array[j+1])
{
//swapping of two using bitwise operator
array[j] = array[j]^array[j+1];
array[j+1] = array[j]^array[j+1];
array[j] = array[j]^array[j+1];
}
}
}
k = x ;
j = n-1;
rec(i,j,k,n,array);
return 0 ;
}
OUTPUT
Enter The Value of Number of Arrays = 4
Enter the Number Which you Want to search in addition of Two Number = 17
Enter The Value of Array
Array[0] = 10
Array[1] = 15
Array[2] = 3
Array[3] = 7
Value equal to sum of array[1] = 7 and array[2] = 10
Process returned 0 (0x0) execution time : 54.206 s
Press any key to continue.
The solution can be found out in just one pass of the array. Initialise a hash Set and start iterating the array. If the current element in the array is found in the set then return true, else add the complement of this element (x - arr[i]) to the set. If the iteration of array ended without returning it means that there is no such pair whose sum is equal to x so return false.
public boolean containsPairWithSum(int[] a, int x) {
Set<Integer> set = new HashSet<>();
for (int i = 0; i< a.length; i++) {
if(set.contains(a[i]))
return true;
set.add(x - a[i]);
}
return false;
}
Here's Python. O(n). Need to remove the current element whilst looping because the list might not have duplicate numbers.
def if_sum_is_k(list, k):
i = 0
list_temp = list.copy()
match = False
for e in list:
list_temp.pop(i)
if k - e in list_temp:
match = True
i += 1
list_temp = list.copy()
return match
I came up with two solutions in C++. One was a naive brute force type which was in O(n^2) time.
int main() {
int N,K;
vector<int> list;
cin >> N >> K;
clock_t tStart = clock();
for(int i = 0;i<N;i++) {
list.push_back(i+1);
}
for(int i = 0;i<N;i++) {
for(int j = 0;j<N;j++) {
if(list[i] + list[j] == K) {
cout << list[i] << " " << list[j] << endl;
cout << "YES" << endl;
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
return 0;
}
}
}
cout << "NO" << endl;
printf("Time taken: %f\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
return 0;}
This solution as you could imagine will take a large amount of time on higher values of input.
My second solution I was able to implement in O(N) time. Using an unordered_set, much like the above solution.
#include <iostream>
#include <unordered_set>
#include <time.h>
using namespace std;
int main() {
int N,K;
int trig = 0;
int a,b;
time_t tStart = clock();
unordered_set<int> u;
cin >> N >> K;
for(int i = 1;i<=N;i++) {
if(u.find(abs(K - i)) != u.end()) {
trig = 1;
a = i;
b = abs(K - i);
}
u.insert(i);
}
trig ? cout << "YES" : cout << "NO";
cout << endl;
cout << a << " " << b << endl;
printf("Time taken %fs\n",(double) (clock() - tStart)/CLOCKS_PER_SEC);
return 0;
}
Python Implementation:
The code would execute in O(n) complexity with the use of dictionary. We would be storing the (desired_output - current_input) as the key in the dictionary. And then we would check if the number exists in the dictionary or not. Search in a dictionary has an average complexity as O(1).
def PairToSumK(numList,requiredSum):
dictionary={}
for num in numList:
if requiredSum-num not in dictionary:
dictionary[requiredSum-num]=0
if num in dictionary:
print(num,requiredSum-num)
return True
return False
arr=[10, 5, 3, 7, 3]
print(PairToSumK(arr,6))
Javascript
const findPair = (array, k) => {
array.sort((a, b) => a - b);
let left = 0;
let right = array.length - 1;
while (left < right) {
const sum = array[left] + array[right];
if (sum === k) {
return true;
} else if (sum < k) {
left += 1;
} else {
right -= 1;
}
}
return false;
}
Using HashSet in java we can do it in one go or with time complexity of O(n)
import java.util.Arrays;
import java.util.HashSet;
public class One {
public static void main(String[] args) {
sumPairsInOne(10, new Integer[]{8, 4, 3, 7});
}
public static void sumPairsInOne(int sum, Integer[] nums) {
HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(nums));
//adding values to a hash set
for (Integer num : nums) {
if (set.contains(sum - num)) {
System.out.print("Found sum pair => ");
System.out.println(num + " + " + (sum - num) + " = " + sum);
return;
}
}
System.out.println("No matching pairs");
}
}
Python
def add(num, k):
for i in range(len(num)):
for j in range(len(num)):
if num[i] + num[j] == k:
return True
return False
C# solution:
bool flag = false;
var list = new List<int> { 10, 15, 3, 4 };
Console.WriteLine("Enter K");
int k = int.Parse(Console.ReadLine());
foreach (var item in list)
{
flag = list.Contains(k - item);
if (flag)
{
Console.WriteLine("Result: " + flag);
return;
}
}
Console.WriteLine(flag);
My C# Implementation:
bool isPairPresent(int[] numbers,int value)
{
for (int i = 0; i < numbers.Length; i++)
{
for (int j = 0; j < numbers.Length; j++)
{
if (value - numbers[i] == numbers[j])
return true;
}
}
return false;
}
Here's a javascript solution:
function ProblemOne_Solve()
{
const k = 17;
const values = [10, 15, 3, 8, 2];
for (i=0; i<values.length; i++) {
if (values.find((sum) => { return k-values[i] === sum} )) return true;
}
return false;
}
I implemented with Scala
def hasSome(xs: List[Int], k: Int): Boolean = {
def check(xs: List[Int], k: Int, expectedSet: Set[Int]): Boolean = {
xs match {
case List() => false
case head :: _ if expectedSet contains head => true
case head :: tail => check(tail, k, expectedSet + (k - head))
}
}
check(xs, k, Set())
}
I have tried the solution in Go Lang. However, it consumes O(n^2) time.
package main
import "fmt"
func twoNosAddUptoK(arr []int, k int) bool{
// O(N^2)
for i:=0; i<len(arr); i++{
for j:=1; j<len(arr);j++ {
if arr[i]+arr[j] ==k{
return true
}
}
}
return false
}
func main(){
xs := []int{10, 15, 3, 7}
fmt.Println(twoNosAddUptoK(xs, 17))
}
Here's two very quick Python implementations (which account for the case that inputs of [1,2] and 2 should return false; in other words, you can't just double a number, since it specifies "any two").
This first one loops through the list of terms and adds each term to all of the previously seen terms until it hits the desired sum.
def do_they_add(terms, result):
first_terms = []
for second_term in terms:
for first_term in first_terms:
if second_term + first_term == result:
return True
first_terms.append(second_term)
return False
This one subtracts each term from the result until it reaches a difference that is in the list of terms (using the rule that a+b=c -> c-a=b). The use of enumerate and the odd list indexing is to exclude the current value, per the first sentence in this answer.
def do_they_add_alt(terms, result):
for i, term in enumerate(terms):
diff = result - term
if diff in [*terms[:i - 1], *terms[i + 1:]]:
return True
return False
If you do allow adding a number to itself, then the second implementation could be simplified to:
def do_they_add_alt(terms, result):
for term in terms:
diff = result - term
if diff in terms:
return True
return False
solution in javascript
this function takes 2 parameters and loop through the length of list and inside the loop there is another loop which adds one number to other numbers in the list and check there sum if its equal to k or not
const list = [10, 15, 3, 7];
const k = 17;
function matchSum(list, k){
for (var i = 0; i < list.length; i++) {
list.forEach(num => {
if (num != list[i]) {
if (list[i] + num == k) {
console.log(`${num} + ${list[i]} = ${k} (true)`);
}
}
})
}
}
matchSum(list, k);
My answer to Daily Coding Problem
# Python 2.7
def pairSumK (arr, goal):
return any(map(lambda x: (goal - x) in arr, arr))
arr = [10, 15, 3, 7]
print pairSumK(arr, 17)
Here is the code in Python 3.7 with O(N) complexity :
def findsome(arr,k):
if len(arr)<2:
return False;
for e in arr:
if k>e and (k-e) in arr:
return True
return False
and also best case code in Python 3.7 with O(N^2) complexity :
def findsomen2 (arr,k):
if len(arr)>1:
j=0
if arr[j] <k:
while j<len(arr):
i =0
while i < len(arr):
if arr[j]+arr[i]==k:
return True
i +=1
j +=1
return False
Javascript Solution
function matchSum(arr, k){
for( var i=0; i < arr.length; i++ ){
for(var j= i+1; j < arr.length; j++){
if (arr[i] + arr[j] === k){
return true;
}
}
}
return false;
}

Given an array of 0 and 1, find minimum no. of swaps to bring all 1s together (only adjacent swaps allowed)

If given an array of 1's and 0's, what's good algorithm to show the minimum number of adjacent swaps needed to group all of the 1's together. The 1's don't need to be grouped at any specific place in the array. They just need to be grouped in whatever place provides for the minimum number of adjacent swaps.
For example, if the array looks like this...
1,0,0,1,1,0,1
...the minimum number of adjacent swaps would be 3, because you'd center on index 4 and do the following swaps:
Swap indices 0 and 1, resulting in:
0,1,0,1,1,0,1
Swap indices 1 and 2, resulting in:
0,0,1,1,1,0,1
Swap indices 5 and 6, resulting in:
0,0,1,1,1,1,0
Anyone have a good algorithm for finding the minimum number of adjacent swaps for any array of 1's and 0's?
UPDATED:
The algorithm determines center by just getting an array of all indices of 1's. The center of that array will always hold the center index. Much faster.
oneIndices = array of indices of all 1's in the input
middleOfOnesIndices = round(oneIndices.length/2)-1 // index to the center index
minimumSwaps = 0
foreach index i of oneIndices
minimumSwaps += aboluteValue(oneIndices[middleOfOneIndices]-oneIndices[i])-absoluteValue(middleOfOneIndices-i);
Here's a fiddle to see it in action:
https://jsfiddle.net/3pmwrk0d/6/
This was a fun one. Thanks for the question.
Hi, firstly I would like to suggest that the minimum number of adjacent swaps would be 2 for your given example instead of 3. As just swap index 0 with index 2. So 1 swap from left and 1 swap from right.
Here is my way to find minimum of swaps to bring the array in consecutive 1's form -
Step 1 : First find the centre index for maximum number of consecutive 1's
Step 2 : Parse the left side of array to swap it and count the number of swap in a efficient manner(Do not swap unnecessarily)
Step 3 : Do the same for the right side array
Step 4 : Plus the counts of both side.
Please have a look at my java program based on same strategy :
`public class MinimumSwap
{
//function to find consecutive number index
public static int[] getMaxConsecutiveIndex(List<Integer> array)
{
int desiredIndex = -1;
int count = 0;
int dupDesiredIndex = -1;
int dupCount = 0;
int i = 0;
while(i < array.size())
{
if(array.get(i) == 0)
{
//pass duplcateIndex value to desiredIndex if count is more
if(dupCount > count)
{
desiredIndex = dupDesiredIndex;
count = dupCount;
}
dupDesiredIndex = -1;
dupCount = 0;
}
else
{
if(dupDesiredIndex == -1)
{
dupDesiredIndex = i;
dupCount = 1;
}
else
{
dupCount++;
}
}
i++;
}
return new int[]{desiredIndex,count};
}
public static int swapCount(List<Integer> array,int startIndex, int endIndex, boolean side)
{
// side == false means 0 at the left
// side == true means 1 at the left
System.out.println("startIndex "+startIndex+" endIndex "+endIndex+" side "+side);
int swapCount = 0;
if(side == false)
{
while(startIndex <= endIndex)
{
if(array.get(endIndex) == 0) // swap from the end only if it is 0
{
//check for first 1 from left to swap
while(array.get(startIndex) == 0 && (startIndex != endIndex))
startIndex++;
if(array.get(startIndex) == 1)
{
// now swap
int temp = array.get(startIndex);
array.set(startIndex, array.get(endIndex));
array.set(endIndex,temp);
swapCount++;
endIndex--;
}
}
endIndex--;
}
}
else
{
while(startIndex <= endIndex)
{
if(array.get(startIndex) == 0) // swap from the starting only if it is 0
{
//check for first 1 from right to swap
while(array.get(endIndex) == 0 && (startIndex != endIndex))
endIndex--;
if(array.get(endIndex) == 1)
{
// now swap
int temp = array.get(startIndex);
array.set(startIndex, array.get(endIndex));
array.set(endIndex,temp);
swapCount++;
startIndex++;
}
}
startIndex++;
}
}
return swapCount;
}
public static void main(String...strings)
{
List<Integer> arr = new ArrayList<Integer>();
int temp[] = {0,1,1,0,0,0,1,1,1,0,1,1,1,0,1,1,1,1,0,1};
//int temp[] = {1,0,0,1,1,0,1};
for(int i=0; i<temp.length; i++)
arr.add(temp[i]);
int centerIndex = getMaxConsecutiveIndex(arr)[0];
int consequtivecount = getMaxConsecutiveIndex(arr)[1];
System.out.println("centerIndex "+centerIndex+" consequtivecount "+consequtivecount);
int swapCountLeft = swapCount(arr,0, centerIndex-1, false);
int swapCountRight = swapCount(arr,centerIndex+consequtivecount, arr.size()-1, true);
System.out.println("total swap count "+swapCountLeft+" :: "+swapCountRight);
System.out.println("array after swapping "+arr);
}
}
`
I am not very sure about performance. But as per my knowledge it should not be inefficient. If anyone finds any performance issue please do let me know :)
Approach :
This can be done by finding number of zeroes to the right side of every 1 and add them. In order to sort the array every one always has to perform a swap operation with every zero on its right side.
So the total number of swap operations for a particular 1 in array is the number of zeroes on its right hand side. Find the number of zeroes on right side for every one i.e. the number of swaps and add them all to obtain the total number of swaps.
// Java code to find minimum number of swaps to sort a binary array
class MinimumNumberOfSwapsNeeded {
static int findMinSwaps(int arr[], int n)
{
// Array to store count of zeroes
int noOfZeroes[] = new int[n];
int i, count = 0;
// Count number of zeroes
// on right side of every one.
noOfZeroes[n - 1] = 1 - arr[n - 1];
for (i = n - 2; i >= 0; i--)
{
noOfZeroes[i] = noOfZeroes[i + 1];
if (arr[i] == 0)
noOfZeroes[i]++;
}
// Count total number of swaps by adding number
// of zeroes on right side of every one.
for (i = 0; i < n; i++)
{
if (arr[i] == 1)
count += noOfZeroes[i];
}
return count;
}
// Driver Code
public static void main(String args[])
{
int ar[] = { 0, 0, 1, 0, 1, 0, 1, 1 };
System.out.println(findMinSwaps(ar, ar.length));
}
}
**
Grouping the array of 0's and 1's such that minimum swaps can be calculated in O(2*n) ~ O(n) complexity.**
package com.segregate.array;
import java.util.ArrayList;
import java.util.List;
public class ArraySegregation {
public static void main(String[] args) {
List<Integer> arr = new ArrayList<>();
/*
*
* List -> low high [1 1 0 0 1 0] -> [ 000111] or [111000]
*
* 1 1 0 0 1 0 -> 000111
*/
arr.add(0);
arr.add(0);
arr.add(0);
arr.add(1);
arr.add(1);
arr.add(0);
arr.add(1);
arr.add(0);
arr.add(0);
List<Integer> arr1 = new ArrayList<>(arr);
int low = 0, high = arr.size() - 1;
int counter1 = 0, counter2 = 0;
// case for swaps such that all 0 in the left side.
while (low < high) {
switch (arr.get(low)) {
case 0:
while (arr.get(low) == 0)
low++;
break;
case 1:
while (arr.get(high) == 1)
high--;
swap(low, high, arr);
counter1++;
high--;
low++;
break;
}
}
// case for swaps such that all 0 in the right side.
/*
* [1 1 0 0 1 0] -> 11 1 0 0 0
*
*
*/
low=0;high = arr1.size() - 1;
while (low < high) {
switch (arr1.get(low)) {
case 0:
while (arr1.get(high) == 0)
high--;
swap(low, high, arr1);
counter2++;
high--;
low++;
break;
case 1:
while (arr1.get(low) == 1)
low++;
break;
}
}
int count = (counter1 > counter2) ? counter2 : counter1;
System.out.println(count);
}
private static void swap(int low, int high, List<Integer> arr) {
int temp1 = 0;
temp1 = arr.get(low);// 1
arr.remove(low);
arr.add(low, arr.get(high-1));
arr.remove(high-1);
arr.add(high, temp1);
}
}
Here is a simple, but not very clever algorithm that will perform an exhaustive search for any input in the range [0, 255].
Input:
binary string
Output:
optimal number of steps
number of optimal solutions
one detailed example
var transition = [],
isSolution = [];
function init() {
var msk = [ 3, 6, 12, 24, 48, 96, 192 ],
i, j, n, x, cnt, lsb, msb, sz = [];
for(i = 0; i < 0x100; i++) {
for(n = cnt = msb = 0, lsb = 8; n < 8; n++) {
if(i & (1 << n)) {
cnt++;
lsb = Math.min(lsb, n);
msb = Math.max(msb, n);
}
}
sz[i] = msb - lsb;
isSolution[i] = (sz[i] == cnt - 1);
}
for(i = 0; i < 0x100; i++) {
for(j = 0, transition[i] = []; j < 0x100; j++) {
x = i ^ j;
if(msk.indexOf(x) != -1 && (x & i) != x && (x & j) != x && sz[j] <= sz[i]) {
transition[i].push(j);
}
}
}
}
function solve() {
var x = parseInt(document.getElementById('bin').value, 2),
path = [ x ],
list = [],
i, min, sol = [], res = [];
recurse(x, path, list);
for(i in list) {
if(min === undefined || list[i].length <= min) {
min = list[i].length;
(sol[min] = (sol[min] || [])).push(list[i]);
}
}
console.log('Optimal length: ' + (min - 1) + ' step(s)');
console.log('Number of optimal solutions: ' + sol[min].length);
console.log('Example:');
for(i in sol[min][0]) {
res.push(('0000000' + sol[min][0][i].toString(2)).substr(-8, 8));
}
console.log(res.join(' -> '));
}
function recurse(x, path, list) {
if(isSolution[x]) {
list.push(path);
return;
}
for(i in transition[x]) {
if(path.indexOf(y = transition[x][i]) == -1) {
recurse(y, path.slice().concat(y), list);
}
}
}
init();
<input id="bin" maxlength="8" placeholder="enter binary string">
<button onclick="solve()">solve</button>

Get longest continuous sequence of 1s

I recently encountered a problem statement it says:
Given an array of 0s and 1s, find the position of 0 to be
replaced with 1 to get longest continuous sequence of 1s.
For example : Array- 1,1,0,0,1,0,1,1,1,0,1,1,1
Output - index 9
I tried a brute force approach replacing every encountered 0 with 1 and after each such replacement, i counted the largest continuous repetitive sequence of 1 and updated it every time.
Is there a better approach/algorithm to this problem?
There should be a one-pass solution to this. The overall idea is to count the ones and to add up the lengths for each zero as you go. Well, not each zero, just the last encountered one and the longest.
You need to keep track of two things:
The longest chain so far.
The previous zero value, along with the length of the preceding ones.
The process then goes as following:
Starting walking through the string until you encounter a zero. Keep track of the number of ones as you go.
When you hit the zero, remember the position of the zero along with the number of preceding 1s.
Count the 1s to the next zero.
Go back to the previous zero and add the new "ones" to the previous "ones". If this is longer than the longest chain, then replace the longest chain.
Remember this zero along with the preceding 1s.
Repeat until you have reached the end of the string.
At then end of the string, go back and add the length to the previous zero and replace the longest chain if appropriate.
You can imagine you have to maintain a set of 1 allowing only one 0 among them,
so
1) walk over the array,
2) if you are getting a 1,
check a flag if you are already in a set, if no,
then you start one and keep track of the start,
else if yes, you just update the end point of set
3) if you get a 0, then check if it can be included in the set,
(i.e. if only one 0 surrounded by 1 "lonely zero" )
if no, reset that flag which tells you you are in a set
else
is this first time ? (store this 0 pos, initialized to -1)
yes, then just update the zero position
else okk, then previous set, of one..zero..one gets finished here,
now the new set's first half i.e. first consecutive ones are the previous set's last portion,
so set the beginning of the set marker to last zero pos +1, update the zero position.
So when to get check if the current set is having highest length? See , we update the end point only in 2 -> else portion, so just check with max start, max end etc etc at that point and it should be enough
Here is my solution. It is clean, takes O(n) time and O(1) memory.
public class Q1 {
public Q1() {
}
public static void doit(int[] data) {
int state = 0;
int left, right, max_seq, max_i, last_zero;
left = right = 0;
max_seq = -1;
max_i = -1;
// initialization
right = data[0];
last_zero = (data[0]==0) ? 0 : -1;
for (int i = 1; i < data.length; i++) {
state = data[i - 1] * 10 + data[i];
switch (state) {
case 00: //reset run
left = right = 0;
last_zero = i;
break;
case 01: // beginning of a run
right++;
break;
case 10:// ending of a run
if(left+right+1>max_seq){
max_seq = left+right+1;
max_i = last_zero;
}
last_zero = i; //saving zero position
left = right; // assigning left
right = 0; // resetting right
break;
case 11: // always good
right++;
break;
}
}
//wrapping up
if(left+right+1>max_seq){
max_seq = left+right+1;
max_i = last_zero;
}
System.out.println("seq:" + max_seq + " index:" + max_i);
}
public static void main(String[] args) {
//Q1.doit(new int[] { 1,1,0,0,1,0,1,1,1,0,1,1,1 });
Q1.doit(new int[] { 1,1,0,0,1,0,1,1,1,0,1,1,1 });
}
}
Using Dynamic programming you can solve this code.
Time complexity is O(n) and space complexity is O(n).
public static int Flipindex(String mystring){
String[] arr = mystring.split(",");
String [] arrays= new String[arr.length];
for(int i=0;i<arr.length;i++){
arrays[i]="1";
}
int lastsum = 0;
int[] sumarray =new int[arr.length];
for(int i=0;i<arr.length;i++){
if(!arr[i].equals(arrays[i])){
++lastsum;
}
sumarray[i]=lastsum;
}
int [] consecsum = new int [sumarray[sumarray.length-1]+1];
for(int i: sumarray){
consecsum[i]+=1;
}
int maxconsecsum=0,startindex=0;
for(int i=0;i<consecsum.length-1;i++){
if((consecsum[i]+consecsum[i+1])>maxconsecsum){
maxconsecsum=(consecsum[i]+consecsum[i+1]);
startindex=i;
}
}
int flipindex=0;
for(int i=0;i<=startindex;i++){
flipindex+=consecsum[i];
}
return flipindex;
}
public static void main(String[] args) {
String s= "1,1,0,0,1,0,1,1,1,0,1,1,1";
System.out.println(Flipindex(s));
}
Playing around with console yielded me this, touch up and cover edge case then you are good to go
function getIndices(arr, val) {
var indexes = [], i = -1;
while ((i = arr.indexOf(val, i+1)) != -1){
indexes.push(i);
}
return indexes;
}
var a = [1,1,1,1,1,0,0,1,0,0,1,1,1,0,1,1,1,1,1,1,0];
var z = getIndices(a, 0);
z.unshift(0);
var longestchain = 0;
var target = 0;
for(var i=0;i<z.length;i++) {
if(i == 0) { //first element
longestchain = z[i] + z[i+1];
target = i;
} else if (i == z.length-1) { //last element
var lastDistance = Math.abs(z[i] - z[i-1]);
if(lastDistance > longestchain) {
longestchain = lastDistance;
target = i;
}
} else {
if(Math.abs(z[i] - z[i+1]) > 1) { //consecutive 0s
//look before and ahead
var distance = Math.abs(z[i-1] - z[i]) + Math.abs(z[i] - z[i+1]);
if(distance > longestchain) {
longestchain = distance;
target = i;
}
}
}
}
console.log("change this: " + z[target]);
I first search for zeroes in the array and stored the position in another array, so in my e.g. you will get something like this [0,5,6,8,9,13,20], then i just run a single loop to find the greatest distance from each element with their adjacent ones, and storing the distance in the "longestchain", everytime i find a longer chain, i take note of the index, in this case "13".
This C code implementation is based on the algorithm provided by #gordon-linoff above.
int maxOnesIndex1(bool arr[], int n)
{
int prevZeroPos = 0;
int oldOneCnt = 0;
int newOneCnt = 0;
int longestChainOfOnes = 0;
int longestChainPos = 0;
int i;
for(i=0; i<n; i++)
{
if(arr[i]!=0)
{
oldOneCnt++;
}
else // arr[i] == 0
{
prevZeroPos = i;
newOneCnt = 0;
// move by one to find next sequence of 1's
i++;
while(i<n && arr[i] == 1)
{
i++;
newOneCnt++;
}
if((oldOneCnt+newOneCnt) > longestChainOfOnes)
{
longestChainOfOnes = oldOneCnt+newOneCnt+1;
longestChainPos = prevZeroPos;
}
oldOneCnt = 0;
i = prevZeroPos;
}
}
if((oldOneCnt+newOneCnt) > longestChainOfOnes)
{
longestChainOfOnes = oldOneCnt+newOneCnt+1;
longestChainPos = prevZeroPos;
}
return longestChainPos;
}
Space Complexity - O(1)
Time Complexity - O(n)
A = map(int, raw_input().strip().split(' '))
left = 0 #Numbers of 1 on left of current index.
right = 0 #Number of 1 on right of current index.
longest = 0 #Longest sequence so far
index = 0
final_index = 0 # index of zero to get the longest sequence
i = 0
while i < A.__len__():
if A[i] == 0:
left = right
index = i
i += 1
right = 0
while i < A.__len__() and A[i] != 0:
right += 1
i += 1
if left + right + 1 > longest:
final_index = index
longest = left + right + 1
else:
right += 1
i += 1
print final_index, longest
Here is little different algorithm
public static int zeroIndexToGetMaxOnes(int[] binArray) {
int prevPrevIndex = -1, prevIndex = -1,currentLenght= -1, maxLenght = -1, requiredIndex = -1;
for (int currentIndex = 0; currentIndex < binArray.length; currentIndex++) {
if (binArray[currentIndex] == 0) {
if (prevPrevIndex != -1) {
currentLenght = currentIndex - (prevPrevIndex + 1);
if (currentLenght > maxLenght) {
maxLenght = currentLenght;
requiredIndex = prevIndex;
}
}
prevPrevIndex = prevIndex;
prevIndex = currentIndex;
} else {// case when last element is not zero, and input contains more than 3 zeros
if (prevIndex != -1 && prevPrevIndex != -1) {
currentLenght = currentIndex - (prevPrevIndex + 1);
if (currentLenght > maxLenght) {
maxLenght = currentLenght;
requiredIndex = prevIndex;
}
}
}
}
if (maxLenght == -1) { // less than three zeros
if (prevPrevIndex != -1) { // 2 zeros
if (prevIndex > (binArray.length - prevPrevIndex - 1)) {
requiredIndex = prevPrevIndex;
} else {
requiredIndex = prevIndex;
}
} else { // one zero
requiredIndex = prevIndex;
}
}
return requiredIndex;
}
Here is the unit tests
#Test
public void replace0ToGetMaxOnesTest() {
int[] binArray = {1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1};
int index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(9));
binArray = new int[]{1,0,1,1,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(1));
binArray = new int[]{0,1,1,1,0,1};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(4));
binArray = new int[]{1,1,1,0,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(3));
binArray = new int[]{0,1,1,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(4));
binArray = new int[]{1,1,1,1,0};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(4));
binArray = new int[]{0,1,1,1,1};
index = ArrayUtils.zeroIndexToGetMaxOnes(binArray);
assertThat(index, is(0));
}
def sol(arr):
zeros = [idx for idx, val in enumerate(arr) if val == 0]
if len(arr) == 0 or len(zeros) == 0:
return None
if len(arr) - 1 > zeros[-1]:
zeros.append(len(arr))
if len(zeros) == 1:
return zeros[0]
if len(zeros) == 2:
return max(zeros)
max_idx = None
diff = 0
for i in range(len(zeros) - 2):
# Calculating the difference of i+2 and i, since i+1 should be filled with 1 to find the max index
if zeros[i+2] - zeros[i] > diff:
diff = zeros[i + 2] - zeros[i] - 1
max_idx = zeros[i+1]
return max_idx
arr = [1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1]
print(sol(arr))

Using two Arrays in C/Gameboy programming

For a game in Gameboy programming, I am using four arrays called top, oldTop, bottom and oldBottom:
struct Point { int x, y; };
struct Rect { struct Point xx, yy; };
Rect top[size], oldTop[size];
Rect bottom[size], oldBottom[i];
where Rect is a struct made of two Struct Points, the top-left and the bottom right corner points.
The idea of the game is to have random-heighted blocks top-down from the ceiling and bottom-up from the floor.
It is similar to the copter-classic game. In my infinite while loop, I shift all of the rectangles down by one pixel using the following code
while (1)
{
for (int i = 0; i < size; i++)
{
//in Struct Rect, xx is the top-left corner point, and yy is the bottom right
top[i].xx.x--;
top[i].yy.x--;
bottom[i].xx.x--;
bottom[i].yy.x--;
if (top[i].xx.x < 0)
{
top[i].xx.x += 240;
top[i].yy.x += 240;
}
if (bottom[i].xx.x < 0)
{
bottom[i].xx.x += 240;
bottom[i].yy.x += 240;
}
}
for (int i = 0; i < size; i++)
{
drawRect(oldTop[i], colorBlack);
drawRect(oldBottom[i], colorBlack);
}
/*call delay function that wait for Vertical Blank*/
for(int i = 0; i < size; i++)
{
drawRect(top[i], colorGreen);
drawRect(bottom[i], colorGreen);
oldTop[i] = top[i];
oldBottom[i] = bottom[i];
}
}
The drawRect method uses DMA to draw the rectangle.
with this code, the code should display the rectangles like this: (drew this up in paint)
But the result I get is
What is odd is that if I don't draw the bottom row at all, then the top row draws fine. The result only messes up when I draw both. This is really weird because I think that the code should be working fine, and the code is not very complicated. Is there a specific reason this is happening, and is there a way to remedy this?
Thanks.
The code that I use to draw the rectangle looks like this:
void drawRect(int row, int col, int width, int height){
int i;
for (i=0; i<height; i++)
{
DMA[3].src = &color;
DMA[3].dst = videoBuffer + (row+r)*240 + col);
DMA[3].cnt = DMA_ON | DMA_FIXED_SOURCE | width;
}
}
Here's a debugging SSCCE (Short, Self-Contained, Correct Example) based on your code. There are assertions in this code that fire; it runs, but is known not to be correct. I've renamed bottom to btm and oldBottom to oldBtm so that the names are symmetric; it makes the code layout more systematic (but is otherwise immaterial).
#include <assert.h>
#include <stdio.h>
typedef struct Point { int x, y; } Point;
typedef struct Rect { struct Point xx, yy; } Rect;
enum { size = 2 };
typedef enum { colourGreen = 0, colourBlack = 1 } Colour;
/*ARGSUSED*/
static void drawRect(Rect r, Colour c)
{
printf(" (%3d)(%3d)", r.xx.x, r.yy.x);
}
int main(void)
{
Rect top[size], oldTop[size];
Rect btm[size], oldBtm[size];
int counter = 0;
for (int i = 0; i < size; i++)
{
top[i].xx.x = 240 - 4 * i;
top[i].xx.y = 0 + 10 + i;
top[i].yy.x = 240 - 14 * i;
top[i].yy.y = 0 + 20 + i;
btm[i].xx.x = 0 + 72 * i;
btm[i].xx.y = 0 + 10 * i;
btm[i].yy.x = 0 + 12 * i;
btm[i].yy.y = 0 + 20 * i;
oldTop[i] = top[i];
oldBtm[i] = btm[i];
}
while (1)
{
if (counter++ > 480) // Limit amount of output!
break;
for (int i = 0; i < size; i++)
{
//in Struct Rect, xx is the top-left corner point, and yy is the bottom right
top[i].xx.x--;
top[i].yy.x--;
btm[i].xx.x--;
btm[i].yy.x--;
if (top[i].xx.x < 0)
{
top[i].xx.x += 240;
top[i].yy.x += 240;
}
if (btm[i].xx.x < 0)
{
btm[i].xx.x += 240;
btm[i].yy.x += 240;
}
}
for (int i = 0; i < size; i++)
{
assert(top[i].xx.x >= 0 && top[i].yy.x >= 0);
assert(btm[i].xx.x >= 0 && btm[i].yy.x >= 0);
}
for (int i = 0; i < size; i++)
{
drawRect(oldTop[i], colourBlack);
drawRect(oldBtm[i], colourBlack);
}
/*call delay function that wait for Vertical Blank*/
for(int i = 0; i < size; i++)
{
drawRect(top[i], colourGreen);
drawRect(btm[i], colourGreen);
oldTop[i] = top[i];
oldBtm[i] = btm[i];
}
putchar('\n');
}
return(0);
}
As noted in a late comment, one big difference between this and your code is that oldBottom in your code is declared as:
Rect top[size], oldTop[size];
Rect bottom[size], oldBottom[i];
using the size i instead of size. This probably accounts for array overwriting issues you see.
There's a second problem though; the assertions in the loop in the middle fire:
(240)(240) ( 0)( 0) (236)(226) ( 72)( 12) (239)(239) (239)(239) (235)(225) ( 71)( 11)
(239)(239) (239)(239) (235)(225) ( 71)( 11) (238)(238) (238)(238) (234)(224) ( 70)( 10)
(238)(238) (238)(238) (234)(224) ( 70)( 10) (237)(237) (237)(237) (233)(223) ( 69)( 9)
(237)(237) (237)(237) (233)(223) ( 69)( 9) (236)(236) (236)(236) (232)(222) ( 68)( 8)
(236)(236) (236)(236) (232)(222) ( 68)( 8) (235)(235) (235)(235) (231)(221) ( 67)( 7)
(235)(235) (235)(235) (231)(221) ( 67)( 7) (234)(234) (234)(234) (230)(220) ( 66)( 6)
(234)(234) (234)(234) (230)(220) ( 66)( 6) (233)(233) (233)(233) (229)(219) ( 65)( 5)
(233)(233) (233)(233) (229)(219) ( 65)( 5) (232)(232) (232)(232) (228)(218) ( 64)( 4)
(232)(232) (232)(232) (228)(218) ( 64)( 4) (231)(231) (231)(231) (227)(217) ( 63)( 3)
(231)(231) (231)(231) (227)(217) ( 63)( 3) (230)(230) (230)(230) (226)(216) ( 62)( 2)
(230)(230) (230)(230) (226)(216) ( 62)( 2) (229)(229) (229)(229) (225)(215) ( 61)( 1)
(229)(229) (229)(229) (225)(215) ( 61)( 1) (228)(228) (228)(228) (224)(214) ( 60)( 0)
Assertion failed: (btm[i].xx.x >= 0 && btm[i].yy.x >= 0), function main, file video.c, line 63.
I think your 'not negative' checks should be revised to:
if (top[i].xx.x < 0)
top[i].xx.x += 240;
if (top[i].yy.x < 0)
top[i].yy.x += 240;
if (btm[i].xx.x < 0)
btm[i].xx.x += 240;
if (btm[i].yy.x < 0)
btm[i].yy.x += 240;
This stops anything going negative. However, it is perfectly plausible that you should simply be checking on the bottom-right x-coordinate (instead of the top-left coordinate) using the original block. Or the wraparound may need to be more complex altogether. That's for you to decipher. But I think that the odd displays occur because you were providing negative values where you didn't intend to and weren't supposed to.
The key points to note here are:
When you're debugging an algorithm, you don't have to use the normal display mechanisms.
When you're debugging, reduce loop sizes where you can (size == 2).
Printing just the relevant information (here, the x-coordinates) helped reduce the output.
Putting the counter code to limit the amount of output simplifies things.
If things are going wrong, look for patterns in what is going wrong early.
I had various versions of the drawRect() function before I got to the design shown, which works well on a wide screen (eg 120x65) terminal window.

Identify the index corresponding to the smallest data in a set of arrays

This is a trivial algorithmic question, I believe, but I don't seem to be able to find an efficient and elegant solution.
We have 3 arrays of int (Aa, Ab, Ac) and 3 cursors (Ca, Cb, Cc) that indicate an index in the corresponding array. I want to identify and increment the cursor pointing to the smallest value. If this cursor is already at the end of the array, I will exclude it and increment the cursor pointing to the second smallest value. If there is only 1 cursor that is not at the end of the array, we increment this one.
The only solutions I can come up are complicated and/or not optimal. For example, I always end up with a huge if...else...
Does anyone see a neat solution to this problem ?
I am programming in C++ but feel free to discuss it in pseudo-code or any language you like.
Thank you
Pseudo-java code:
int[] values = new int[3];
values[0] = aa[ca];
values[1] = ab[cb];
values[2] = ac[cc];
Arrays.sort(values);
boolean done = false;
for (int i = 0; i < 3 && !done; i++) {
if (values[i] == aa[ca] && ca + 1 < aa.length) {
ca++;
done = true;
}
else if (values[i] == ab[cb] && cb + 1 < ab.length) {
cb++;
done = true;
}
else if (cc + 1 < ac.length) {
cc++;
done = true;
}
}
if (!done) {
System.out.println("cannot increment any index");
stop = true;
}
Essentially, it does the following:
initialize an array values with aa[ca], ab[cb] and ac[cc]
sort values
scan values and increment if possible (i.e. not already at the end of the array) the index of the corresponding value
I know, sorting is at best O(n lg n), but I'm only sorting an array of 3 elements.
what about this solution:
if (Ca != arraySize - 1) AND
((Aa[Ca] == min(Aa[Ca], Ab[Cb], Ac[Cc]) OR
(Aa[Ca] == min(Aa[Ca], Ab[Cb]) And Cc == arraySize - 1) OR
(Aa[Ca] == min(Aa[Ca], Ac[Cc]) And Cb == arraySize - 1) OR
(Cc == arraySize - 1 And Cb == arraySize - 1))
{
Ca++;
}
else if (Cb != arraySize - 1) AND
((Ab[Cb] == min(Ab[Cb], Ac[Cc]) OR (Cc == arraySize - 1))
{
Cb++;
}
else if (Cc != arraySize - 1)
{
Cc++;
}
Pseudo code: EDIT : tidied it up a bit
class CursoredArray
{
int index;
std::vector<int> array;
int val()
{
return array[index];
}
bool moveNext()
{
bool ret = true;
if( array.size() > index )
++index;
else
ret = false;
return ret;
}
}
std::vector<CursoredArray> arrays;
std::vector<int> order = { 0, 1, 2 };//have a default order to start with
if( arrays[0].val() > arrays[1].val() )
std::swap( order[0], order [1] );
if( arrays[2].val() < arrays[order[1]].val() )//if the third is less than the largest of the others
{
std::swap( order[1], order [2] );
if( arrays[2].val() < arrays[order[0]].val() )//if the third is less than the smallest of the others
std::swap( order[0], order [1] );
}
//else third pos of order is already correct
bool end = true;
for( i = 0; i < 3; ++i )
{
if( arrays[order[i]].MoveNext() )
{
end = false;
break;
}
}
if( end )//have gone through all the arrays

Resources