Related
I have a question, in one of the algorithms, I had written, to seperate out, all the even numbers to the left and odd numbers to the right.
Example: Input:
{ 12, 10, 52, 57, 14, 91, 34, 100, 245, 78, 91, 32, 354, 80, 13, 67, 65 }
Output:
{12,10,52,80,14,354,34,100,32,78,91,245,91,57,13,67,65}
Below is the algorithm
public int[] sortEvenAndOdd(int[] combinedArray) {
int endPointer = combinedArray.length - 1;
int startPointer = 0;
for (int i = endPointer; i >= startPointer; i--) {
if (combinedArray[i] % 2 == 0) {
if (combinedArray[startPointer] % 2 != 0) {
int temp = combinedArray[i];
combinedArray[i] = combinedArray[startPointer];
combinedArray[startPointer] = temp;
startPointer = startPointer + 1;
} else {
while (combinedArray[startPointer] % 2 == 0 &&
(startPointer != i)) {
startPointer = startPointer + 1;
}
int temp = combinedArray[i];
combinedArray[i] = combinedArray[startPointer];
combinedArray[startPointer] = temp;
startPointer = startPointer + 1;
}
}
}
return combinedArray;
}
Anybody, have any suggestions, for it make it to O(n) or better ?
Your code is O(n), but it's a bit more complicated than it needs to be. Here's an improvement.
startPointer = 0;
endPointer = a.length - 1;
while (startPointer < endPointer)
{
if (a[startPointer] % 2 != 0)
{
// move endPointer backwards to even number
while (endPointer > startPointer && a[endPointer] % 2 != 0)
{
--endPointer;
}
swap(a[startPointer], a[endPointer]);
}
++startPointer;
}
By the way, the operation is more of a partition than a sort. I think a better function name would be partitionEvenOdd.
Make two queue one for even and another for odd . When any new number come push into respective queue and when all number finished then traverse first even queue and push into answer vector and then odd queue number . This is O(n) solution .I hope I am able to explain the solution .
Sorry for english.
If you want then I can post implementation but you should try.
You can't do it better than O(n) time, but you can make your code more concise.
Looking at your solution, since order of elements doesn't matter, you can simply keep a pointer variable which goes from last to first and keep swapping elements with this pointer.
Snippet:
private static void solve(int[] arr){
for(int i=arr.length-1,ptr = i;i>=0;--i){
if((arr[i] & 1) == 1){
swap(arr,i,ptr--);
}
}
}
private static void swap(int[] arr,int x,int y){
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
Demo: https://onlinegdb.com/HyKNVMbwL
If the order of the elements matter
You can collect all odd ones in a new list.
Move all even ones to the left.
Assign all odd ones one by one from the list to the array from where even ones ended.
This will increase space complexity to O(n).
Im trying to add settings to a snake game made in processing. I want to have something like easy, normal and hard or something along the lines of that and change the speed and maybe size of the grid. If anyone coudl explain how to id greatly appreciate it!
ArrayList<Integer> x = new ArrayList<Integer>(), y = new ArrayList<Integer>();
int w = 30, h = 30, bs = 20, dir = 2, applex = 12, appley = 10;
int[] dx = {0,0,1,-1}, dy = {1,-1,0,0};
boolean gameover = false;
void setup() {
size(600,600);
x.add(5);
y.add(5);
}
void draw() {
background(255);
for(int i = 0 ; i < w; i++) line(i*bs, 0, i*bs, height); //Vertical line for grid
for(int i = 0 ; i < h; i++) line(0, i*bs, width, i*bs); //Horizontal line for grid
for(int i = 0 ; i < x.size(); i++) {
fill (0,255,0);
rect(x.get(i)*bs, y.get(i)*bs, bs, bs);
}
if(!gameover) {
fill(255,0,0);
rect(applex*bs, appley*bs, bs, bs);
if(frameCount%5==0) {
x.add(0,x.get(0) + dx[dir]);
y.add(0,y.get(0) + dy[dir]);
if(x.get(0) < 0 || y.get(0) < 0 || x.get(0) >= w || y.get(0) >= h) gameover = true;
for(int i = 1; i < x.size(); i++) if(x.get(0) == x.get(i) && y.get(0) == y.get(i)) gameover = true;
if(x.get(0)==applex && y.get(0)==appley) {
applex = (int)random(0,w);
appley = (int)random(0,h);
}else {
x.remove(x.size()-1);
y.remove(y.size()-1);
}
}
} else {
fill(0);
textSize(30);
text("GAME OVER. Press Space to Play Again", 20, height/2);
if(keyPressed && key == ' ') {
x.clear(); //Clear array list
y.clear(); //Clear array list
x.add(5);
y.add(5);
gameover = false;
}
}
if (keyPressed == true) {
int newdir = key=='s' ? 0 : (key=='w' ? 1 : (key=='d' ? 2 : (key=='a' ? 3 : -1)));
if(newdir != -1 && (x.size() <= 1 || !(x.get(1) ==x.get(0) + dx[newdir] && y.get (1) == y.get(0) + dy[newdir]))) dir = newdir;
}
}
You need to break your problem down into smaller steps:
Step one: Can you store the difficulty in a variable? This might be an int that keeps track of a level, or a boolean that switches between easy and hard. Just hardcode the value of that variable for now.
Step two: Can you write your code so it changes behavior based on the difficulty level? Use the variable you created in step one. You might use an if statement to check the difficulty level, or maybe the speed increases over time. It's completely up to you. Start out with a hard-coded value. Change the value to see different behaviors.
Step three: Can you programatically change that value? Maybe this requires a settings screen where the user chooses the difficulty, or maybe it gets more difficult over time. But you have to do the first two steps before you can start this step.
If you get stuck on a specific step, then post an MCVE and we'll go from there.
I've create a code for a "generative" logo {Like this http://ebologna.it/ } (it's at the start so is not complete), and I want that while pressing one time the BACKSPACE I can go back just for one shape. Now like I have my code, when I press Backspace it delete all.
Below is the code:
import controlP5.*;
ControlP5 cp5;
String textValue = "";
String val;
void setup() {
size(700,800);
PFont font = createFont("arial",20);
cp5 = new ControlP5(this);
cp5.addTextfield("INPUT")
.setPosition(width/2-100,600)
.setSize(200,40)
.setFont(font)
.setFocus(true)
.setColor(color(255,255,255))
;
textFont(font);
background(0);
noStroke();
}
void draw() {
if (keyPressed) {
if (key == 'o' || key == 'O') {
fill(205, 152, 59, 100);
ellipse(width/2, height/2, 50, 50);
}
if (key == 'b' || key == 'B') {
fill(20, 84, 42, 100);
rectMode(CENTER);
rect(width/2, height/2, 50, 50);
}
}
if (key == BACKSPACE) { //This reset all, I want to reset just the last one shape
background (0);
}
val = cp5.get(Textfield.class,"INPUT").getText();
println(val.length());
}
Thanks !
Another option is to use a for loop to go through each character of the text String and draw the corresponding shape.
A for loop may look complicated because of it's syntax but it's not too bad if you look at it as a way of repeating a set of instructions for a given number of times/steps. The syntax roughly like so:
for( intial step ; condition to stop ; incrementation ){
//something to repeat while the condition to stop is still false
}
think of walking 10 steps, one step a time:
for(int step = 0 ; step < 10 ; step = step+1){
println("step index: " + i);
}
If you can do one step at a time, you can also hop:
for(int step = 0 ; step < 10 ; step = step+2){
println("step index: " + i);
}
Going back to your challenge, you can use a for loop to go through each character of the text. For example:
String text = "go";
for(int letterIndex = 0 ; letterIndex < text.length(); letterIndex = letterIndex + 1){
//get the character
char letter = text.charAt(letterIndex);
println(letter);
}
The snippet above uses String's length() function to retrieve the number of characters and the charAt() to retrieve a character by it's index in the String
Applied to your code:
import controlP5.*;
ControlP5 cp5;
void setup() {
size(700,800);
PFont font = createFont("arial",20);
cp5 = new ControlP5(this);
cp5.addTextfield("INPUT")
.setPosition(width/2-100,600)
.setSize(200,40)
.setFont(font)
.setFocus(true)
.setColor(color(255,255,255));
textFont(font);
background(0);
noStroke();
}
void draw() {
background (0);
//get the text string
String text = cp5.get(Textfield.class,"INPUT").getText();
//loop through each character
for(int letterIndex = 0 ; letterIndex < text.length(); letterIndex = letterIndex + 1){
//get the character
char letter = text.charAt(letterIndex);
//draw the coresponding shape
if (letter == 'o' || letter == 'O') {
fill(205, 152, 59, 100);
ellipse(width/2, height/2, 50, 50);
}
if (letter == 'b' || letter == 'B') {
fill(20, 84, 42, 100);
rectMode(CENTER);
rect(width/2, height/2, 50, 50);
}
}
}
If you want to be able to change what's been drawn to the screen, you're going to have to take this approach:
Step 1: Store everything you need to draw to the screen in a data structure. For you, this might be an ArrayList that holds instances of a Circle class that you create.
Step 2: Every single time draw() is called, clear the previous frames by calling the background() function, and then draw everything in the data structure to the screen.
Step 3: To modify what's on the screen, just modify what's in the data structure. For you, you might remove the Circle in the last position of the ArrayList.
I have a collection of measurments, example:
measurment #1: { 200, 350, 712, 1023, 1430, 1555, 1800, 2036, 2569 }
measurment #2: { 165, 400, 974, 1124, 1600, 1893, 1919, 2032, 2654, 2932 }
...
measurment #N: { 234, 454, 879, 1432, 1877, 2000, 2543, 2876 }
The order of the elements in each measurment is important.
Each element will have higher value than the previous.
The number of elements in each measurment may vary,
but they should not vary to much.
Now i am getting as an input a new measurment
(lets say: { 212, 354, 978, 1222, 1454, 1922, 2013, 2432, 2987})
and should find the closest measurment from the collection of measurment i already possess.
My question is what algorithm should i use for this task ?
More:
1. It is also possible to extend the task in such meatter that instead input of one measurment i will be given a small collection of measurments.
2. Each element in a measurment represent time passed in second from the begining.
The measuring is stoped when reached 3600 seconds (1 hour), therfore the minimal posible value will be 0 and the maximal will be 3599.
The events creating each element in the measurment to be created is affected by a human behaviour.
Thanks for your help :)
Assuming that your data is "fuzzy", one class of algorithms you may want to look into is dynamic programming. By fuzzy I mean that two sets are almost align, but one set may have extra elements inserted, removed compared to the other and the matching elements "almost" matches.
In these types of algorithms you typically define a distance score by defining a penalty for inserting/removing an element in the alignment and a penalty score for two elements not quite matching.
In your case you may define an insert / delete penalty of "100" seconds for inserting an extra timing event, and a two-element distance score as the absolute distance in seconds.
Given that definition you can easily find and modify a needleman-wunsch algorithm implementation or something similar. This will give you the distance between two small sets of measurements in an acceptable amount of time.
However, if your number of elements in your measurements is huge or your number of sets is huge, and you need the answer in say milliseconds, then it is a rather difficult problem unless you can find a lot of good constraints for your problem.
The above is just an example, it all boils down to the context. Is your data noisy? How "noisy", with extra elements in the middle, start or end or just slightly off in position? plus a ton of other questions.
Choosing and implementing fuzzy algorithms can range between pretty easy to near impossible all depending on the context and what you are going to use the result for. Does it need to be exact or "just good enough". Does it need to be fast, etc.
Find the squared sum of errors of your new measure with each measurement in your collection. Then return the one from your collection with the smallest error.
var measures = [
[1, 2, 3, 4],
[10, 20, 30, 40],
[66, 77, 88, 99],
[101, 202, 303, 404]
];
// ignores measurements that aren't the same length as the data
// uses the squared sum of differences (errors)
function findClosest(data) {
var minError = 0x7FFFFFFF; // max 32bit signed int
var result = null;
for(var i=0; i < measures.length; i++) {
if(data.length !== measures[i].length) { continue; }
var error = 0;
for(var j=0; j < data.length; j++) {
error += Math.pow(measures[i][j] - data[j], 2);
}
if(error < minError) {
minError = error;
result = measures[i];
}
}
return result;
}
// allows data that is different length than measurements by trying to best fit each element of data to an element of the tested measurement
// uses the squared sum of differences (error)
function findClosestV2(data) {
var minError = 0x7FFFFFFF; // max 32bit signed int
var result = null;
for(var i=0; i < measures.length; i++) {
var measure = measures[i];
var error = 0;
var minLocalError = 0x7FFFFFFF;
for(var j=0; j < data.length; j++) {
for(var k=0; k < measure.length; k++) {
var localError = Math.pow(measure[k] - data[j], 2);
if(localError < minLocalError) {
minLocalError = localError;
}
}
error += minLocalError;
}
if(error < minError) {
minError = error;
result = measures[i];
}
}
return result;
}
// allows data that is different length than measurements by trying to best fit each element of data to an element of the tested measurement
// uses the average of the absolute error % using the previous measurement as the ideal value
function findClosestV3(data) {
var minError = 0x7FFFFFFF; // max 32bit signed int
var result = null;
for(var i=0; i < measures.length; i++) {
var measure = measures[i];
var error = 0;
var minLocalError = 0x7FFFFFFF;
for(var j=0; j < data.length; j++) {
for(var k=0; k < measure.length; k++) {
var localError = Math.abs( (measure[k] - data[j]) / measure[k] );
if(localError < minLocalError) {
minLocalError = localError;
}
}
error += minLocalError;
}
// average of sum of error percentages
error /= data.length;
if(error < minError) {
minError = error;
result = measures[i];
}
}
return result;
}
console.log(findClosest([2,3,4,5])); // [1,2,3,4]
console.log(findClosest([70,80,90,100])); // [66,77,88,99]
console.log(findClosest([9,19,304,405])); // [101,202,303,404]
console.log(findClosestV2([404])); // [101,202,303,404]
console.log(findClosestV2([66,67,68,69])); // [66,77,88,99]
console.log(findClosestV2([9,19,304,405])); // [10,20,30,40]
console.log(findClosestV3([404])); // [101,202,303,404]
console.log(findClosestV3([66,67,68,69])); // [66,77,88,99]
console.log(findClosestV3([9,19,304,405])); // [10,20,30,40]
I just wrote a simple iterative radix sort and I'm wondering if I have the right idea.
Recursive implementations seem to be much more common.
I am sorting 4-byte integers (unsigned to keep it simple).
I am using 1-byte as the 'digit'. So I have 2^8=256 buckets.
I am sorting the most significant digit (MSD) first.
After each sort I put them back into array in the order they exist in buckets and then perform the next sort.
So I end up doing 4 bucket sorts.
It seems to work for a small set of data. Since I am doing it MSD I'm guessing that's not stable and may fail with different data.
Did I miss anything major?
#include <iostream>
#include <vector>
#include <list>
using namespace std;
void radix(vector<unsigned>&);
void print(const vector<list<unsigned> >& listBuckets);
unsigned getMaxForBytes(unsigned bytes);
void merge(vector<unsigned>& data, vector<list<unsigned> >& listBuckets);
int main()
{
unsigned d[] = {5,3,6,9,2,11,9, 65534, 4,10,17,13, 268435455, 4294967294,4294967293, 268435454,65537};
vector<unsigned> v(d,d+17);
radix(v);
return 0;
}
void radix(vector<unsigned>& data)
{
int bytes = 1; // How many bytes to compare at a time
unsigned numOfBuckets = getMaxForBytes(bytes) + 1;
cout << "Numbuckets" << numOfBuckets << endl;
int chunks = sizeof(unsigned) / bytes;
for(int i = chunks - 1; i >= 0; --i)
{
vector<list<unsigned> > buckets; // lazy, wasteful allocation
buckets.resize(numOfBuckets);
unsigned mask = getMaxForBytes(bytes);
unsigned shift = i * bytes * 8;
mask = mask << shift;
for(unsigned j = 0; j < data.size(); ++j)
{
unsigned bucket = data[j] & mask; // isolate bits of current chunk
bucket = bucket >> shift; // bring bits down to least significant
buckets[bucket].push_back(data[j]);
}
print(buckets);
merge(data,buckets);
}
}
unsigned getMaxForBytes(unsigned bytes)
{
unsigned max = 0;
for(unsigned i = 1; i <= bytes; ++i)
{
max = max << 8;
max |= 0xFF;
}
return max;
}
void merge(vector<unsigned>& data, vector<list<unsigned> >& listBuckets)
{
int index = 0;
for(unsigned i = 0; i < listBuckets.size(); ++i)
{
list<unsigned>& list = listBuckets[i];
std::list<unsigned>::const_iterator it = list.begin();
for(; it != list.end(); ++it)
{
data[index] = *it;
++index;
}
}
}
void print(const vector<list<unsigned> >& listBuckets)
{
cout << "Printing listBuckets: " << endl;
for(unsigned i = 0; i < listBuckets.size(); ++i)
{
const list<unsigned>& list = listBuckets[i];
if(list.size() == 0) continue;
std::list<unsigned>::const_iterator it = list.begin(); // Why do I need std here!?
for(; it != list.end(); ++it)
{
cout << *it << ", ";
}
cout << endl;
}
}
Update:
Seems to work well in LSD form which it can be modified by changing the the chunk loop in radix as follows:
for(int i = chunks - 1; i >= 0; --i)
Let's look at en example with two-digit decimal numbers:
49, 25, 19, 27, 87, 67, 22, 90, 47, 91
Sorting by the first digit yields
19, 25, 27, 22, 49, 47, 67, 87, 90, 91
Next, you sort by the second digit, yielding
90, 91, 22, 25, 27, 47, 67, 87, 19, 49
Seems wrong, doesn't it? Or isn't this what you are doing? Maybe you can show us the code if I got you wrong.
If you are doing the second bucket sort on all groups with the same first digit(s), your algorithm would be equivalent to the recursive version. It would be stable as well. The only difference is that you'd do the bucket sorts breadth-first instead of depth-first.
You also need to make sure you Sort every bucket from MSD to LSD before reassembling.
Example:
19,76,90,34,84,12,72,38
Sort into 10 buckets [0-9] on MSD
B0=[];B1=[19,12];B2=[];B3=[34,38];B4=[];B5=[];B6=[];B7=[76,72];B8=[84];B9=[90];
if you were to reassemble and then sort again it would not work. Instead recursively sort each bucket.
B1 is sorted into B1B2=[12];B1B9=[19]
Once all have been sorted you can reassemble correctly.