Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 348 349 [350] 351 352 ... 796

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 886127 times)

da_nang

  • Bay Watcher
  • Argonian Overlord
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5235 on: November 21, 2013, 07:02:10 pm »

I think I figured it out when I rewrote everything but the main function.
Code: [Select]
int main() {
  pthread_t philosophers[NUMPHILO];
  int i;//The start of the path to coding hell

  /*Init code*/

  for(i = 0; i<NUMPHILO; i++) {
    if (pthread_create(&philosophers[i], NULL,
                       philo, (void*) &i) != 0) {//Notice it's the same integer literal, same address? The value was always 0 when cast back to int* in the philo function.
//Solution is to use a goddamn different pointer for each thread, malloc this stuff up.
      perror("Error creating thread: ");
      return 1;
    }
    printf("Philosopher %i created.\n", i);
  }

That integer literal was subsequently nuked from orbit for its heresy.
« Last Edit: November 21, 2013, 07:03:52 pm by da_nang »
Logged
"Deliver yesterday, code today, think tomorrow."
Ceterum censeo Unionem Europaeam esse delendam.
Future supplanter of humanity.

MorleyDev

  • Bay Watcher
  • "It is not enough for it to just work."
    • View Profile
    • MorleyDev
Re: if self.isCoder(): post() #Programming Thread
« Reply #5236 on: November 21, 2013, 07:03:04 pm »

The worst part is I have no idea how we're going to set this up so that we can use it efficiently.  We need to be able to test by doing as little more than saving a file and refreshing a browser as is possible.  Short of setting up web servers on each developer's machine and creating testing harnesses of sorts, I don't know how we'll achieve that.  I guess that would work in theory at least.  Pull the repo, make changes to anything you need to your local repo, testing on your machine, then push when it's all done.  It's going to be a pain to set up though.

But the investment pays off when you don't break live every five days :) Continuous integration and continuous delivery 101: Automate as much of everything as you can. If you're live-like environment is difficult to create, imagine how difficult it'll be when all your hardware inevitably breaks and you need to create a new one or you need to provision new hardware.

You can iterate to a CI or even CD environment so long as the culture can change to cope. The next step may be to set-up a live-like test environment and have commits automatically deploy to that for pre-release testing. Then get local machines working for testing and create some automated tests. Then have a CI server that runs those tests and tells you when they fail, optionally shooting people who break the build with nerf gun. Eventually you can automate live deployments, smoke test runnings, the works. Technically it's not as big of a problem as you'd think, usually the biggest obstacles are cultural.

It seems complex, but I know of many places that have iterated through to a CI structure. Heck, my work placement was at one such a place that had made the move to CI and was trying to go to full-blown continuous delivery and deployment.

And for your next challenge, introduce pair programming :) This one even has studies with numbers you can quote!

Disclaimer: I'm one of those "(A)TDD, Continuous Integration and Extreme Programming aren't the future of professional software development: They're the now. If your dev-house isn't doing them, ask yourself: Are you living in the future, or stuck in the past?" people.
« Last Edit: November 21, 2013, 07:31:21 pm by MorleyDev »
Logged

Mego

  • Bay Watcher
  • [PREFSTRING:MADNESS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5237 on: November 21, 2013, 08:49:52 pm »

I think I figured it out when I rewrote everything but the main function.
Code: [Select]
int main() {
  pthread_t philosophers[NUMPHILO];
  int i;//The start of the path to coding hell

  /*Init code*/

  for(i = 0; i<NUMPHILO; i++) {
    if (pthread_create(&philosophers[i], NULL,
                       philo, (void*) &i) != 0) {//Notice it's the same integer literal, same address? The value was always 0 when cast back to int* in the philo function.
//Solution is to use a goddamn different pointer for each thread, malloc this stuff up.
      perror("Error creating thread: ");
      return 1;
    }
    printf("Philosopher %i created.\n", i);
  }

That integer literal was subsequently nuked from orbit for its heresy.

This made me laugh after having a crappy day of unsuccessful debugging. Firing nukes at my own code now.

da_nang

  • Bay Watcher
  • Argonian Overlord
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5238 on: November 22, 2013, 03:34:55 am »

> //Notice it's the same integer literal, same address? The value was always 0 when cast back to int* in the philo function.
> //Solution is to use a goddamn different pointer for each thread, malloc this stuff up.
But the value of i changes, so if this theory is true, every thread would have number 5. 
Still, in philo you could change one line to separate thread numbers.
  int i = *((int *) n);
But using another array is more foolproof.
But wait, it gets better. Passing down the same address to the same integer is probably only part of the reason.

Code: [Select]
int main() {
  pthread_t philosophers[NUMPHILO];
  int i;//The start of the path to coding hell

  /*Init code*/

  for(i = 0; i<NUMPHILO; i++) {
    if (pthread_create(&philosophers[i], NULL,
                       philo, (void*) &i) != 0) {//Notice it's the same integer literal, same address? The value was always 0 when cast back to int* in the philo function.
//Solution is to use a goddamn different pointer for each thread, malloc this stuff up.
      perror("Error creating thread: ");
      return 1;
    }
    printf("Philosopher %i created.\n", i);
  }

  for(i = 0; i<NUMPHILO; i++) {
    //Main thread RESETS i to 0 and is then blocked when waiting for the first thread to finish.
    //Even if the scheduler runs another thread instead of the first one, eventually the main thread gets here
    //RAEG
    pthread_join(philosophers[i], NULL);
  }

 /* Other stuff */
}
Logged
"Deliver yesterday, code today, think tomorrow."
Ceterum censeo Unionem Europaeam esse delendam.
Future supplanter of humanity.

Maklak

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5239 on: November 22, 2013, 05:11:05 am »

// Main thread RESETS i to 0 and is then blocked when waiting for the first thread to finish.
// Even if the scheduler runs another thread instead of the first one, eventually the main thread gets here
Lol, you're right. Even so, my proposal to use an int and not int* in function philo fixes it somewhat. Let's see.

I've modified your code a bit and now they all eat, except 1 who for some reason never eats. Ah, it looks like there is a race going on "i" and thread numbers have to be an array after all.

The code below works. You were correct in your solution to dining philosopher problem, you just failed on some gotchas with pthreads.

Code: [Select]
/* Eating philosophers
   philo.c
   Compile as gcc philo.c -o philo -lpthread
     MinGW: gcc -Wall -Wextra -o philo.exe -g -lpthread -pthread philo.c
*/

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h> 
#include <stdlib.h>
#include <time.h>
#define NUMPHILO 6
#define PORTIONS 50
#define LEFT(n) (n+1)%NUMPHILO
#define RIGHT(n) (n+NUMPHILO-1)%NUMPHILO

int statusForks[NUMPHILO];
int histogram[NUMPHILO];
int platesFinished = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t data = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t forks[NUMPHILO];
int start = 0;

void *philo(void * n);
void ponder(int n);
void eat(int n);
void takeForks(int n);
void putForks(int n);

void *philo(void * n) {
  int i = *((int *) n);
  printf("Philosopher %i created.\n", i);
  while(1) {
    if (start) {
      takeForks(i);
      break;
    }
    _sleep(10);
  }
  return NULL;
}

void ponder(int n){
  printf("Philosopher %i is pondering his existence...\n", n);
  _sleep(100 + rand() % 100);
}

void takeForks(int n){
  while(platesFinished < PORTIONS) {
    ponder(n);
    pthread_mutex_lock(forks+LEFT(n));
    if (statusForks[LEFT(n)] == 1) {
      statusForks[LEFT(n)] = 0;
      pthread_mutex_unlock(forks+LEFT(n));

      pthread_mutex_lock(forks + RIGHT(n));

      if (statusForks[RIGHT(n)] == 1) {
        statusForks[RIGHT(n)] = 0;
        pthread_mutex_unlock(forks+RIGHT(n));
        eat(n);
        putForks(n);
//        pthread_yield();
//        _sleep(10 + rand() % 100);
      }
      else {
        pthread_mutex_unlock(forks+RIGHT(n));
        pthread_mutex_lock(forks+LEFT(n));
        statusForks[LEFT(n)] = 1;
        pthread_mutex_unlock(forks+LEFT(n));
      }
    }
    else {
      pthread_mutex_unlock(forks+LEFT(n));
    }
//    pthread_yield();
//    _sleep(100 + rand() % 100);
  }
}

void eat(int n){
  pthread_mutex_lock(&data);
  if(platesFinished == PORTIONS) {
    printf("No more food for philosopher %i.\n", n);
  }
  else {
    printf("Philosopher %i is gorging on the food!\n", n);
    platesFinished++;
    histogram[n]++;
    printf("Philosopher %i is sated. For now...\n", n);
  }
  pthread_mutex_unlock(&data);
}

void putForks(int n){
  pthread_mutex_lock(forks + LEFT(n));
  pthread_mutex_lock(forks + RIGHT(n));
  statusForks[LEFT(n)] = 1;
  statusForks[RIGHT(n)] = 1;
  pthread_mutex_unlock(forks+RIGHT(n));
  pthread_mutex_unlock(forks+LEFT(n));
}

int main() {
  pthread_t philosophers[NUMPHILO];
  int i;
  int num[NUMPHILO];
  int *ptr = num;
  srand(time(0));
  for(i = 0; i<NUMPHILO; i++) {
    statusForks[i] = 1;
    histogram[i] = 0;
    num[i] = i;
    pthread_mutex_init(&forks[i], NULL);
  }

  //Create philosophers
  for(i = 0; i<NUMPHILO; i++) {
    if (pthread_create(&philosophers[i], NULL,
                       philo, (void*) ptr) != 0) {
      perror("Error creating thread: ");
      return 1;
    }
//    printf("Philosopher %i created.\n", i);
    ptr++;
  }

  //start the dining simulation
  start++;

  for(i = 0; i<NUMPHILO; i++) {
    pthread_join(philosophers[i], NULL);
  }

  for(i = 0; i<NUMPHILO; i++) {
    printf("Philosopher %i ate %i times\n", i, histogram[i]);
  }

  return 0;
}
Logged
Quote from: Omnicega
Since you seem to criticize most things harsher than concentrated acid, I'll take that as a compliment.
On mining Organics
Military guide for FoE mod.
Research: Crossbow with axe and shield.
Dropbox referral

Zrk2

  • Bay Watcher
  • Emperor of the Damned
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5240 on: November 23, 2013, 02:39:04 am »

So what do you guys know about matlab? I have to create a graph out of some data, but the way the code is written I have every entry as a separate variable. I tried using the "dataset" function to make it into a vector, but then that vector contains the variable names of the data as well, so matlab will not graph it. Thoughts? Aside from rewriting the whole thing to produce a single vector, because that will take a prohibitively long time.
Logged
He's just keeping up with the Cardassians.

MagmaMcFry

  • Bay Watcher
  • [EXISTS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5241 on: November 23, 2013, 10:00:29 am »

Okay, first of all, how did you manage to have every entry as a separate variable? Matlab is so damn matrix-typed I have no idea how you managed that. Paste your code, there's no way I can't fix that for you.
Logged

Zrk2

  • Bay Watcher
  • Emperor of the Damned
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5242 on: November 23, 2013, 01:49:09 pm »

It's supposed to use an rng to simulate a dice game, so after it's run through the permutations I have a series of if statements that increment variables by one depending upon the result.

Code: [Select]
%clearing any old data
clc;
clear all;

finaltotal=0;
tot2=0;
tot3=0;
tot4=0;
tot5=0;
tot6=0;
tot7=0;
tot8=0;
tot9=0;
tot10=0;
tot11=0;
tot12=0;

%the loop
for i=1:1000
    %calculating a role of five dice
    a=rng;
    b1=rand(1,1);
    c1=ceil(b1*6);
    b2=rand(1,1);
    c2=ceil(b2*6);
    b3=rand(1,1);
    c3=ceil(b3*6);
    b4=rand(1,1);
    c4=ceil(b4*6);
    b5=rand(1,1);
    c5=ceil(b5*6);
    total1=c1+c2+c3+c4+c5;
    %determing if the player will accept that role
    if (total1>24)
        finaltotal=total1-15;
    elseif (c1==6 || c2==6 || c3==6 || c4==6 || c5==6)
        a=rng;
        b1=rand(1,1);
        c1=ceil(b1*6);
        b2=rand(1,1);
        c2=ceil(b2*6);
        b3=rand(1,1);
        c3=ceil(b3*6);
        b4=rand(1,1);
        c4=ceil(b4*6);
        total2=c1+c2+c3+c4;
        %Computing if this role is acceptable
        if (total2>17)
            finaltotal=total2-9;
        elseif (c1==5 || c2==5 || c3==5 || c4==5 || c5==5)
            a=rng;
            b1=rand(1,1);
            c1=ceil(b1*6);
            b2=rand(1,1);
            c2=ceil(b2*6);
            b3=rand(1,1);
            c3=ceil(b3*6);
            total3=c1+c2+c3;
            %The player can take another chance
            if (total3>12)
                finaltotal=total3-4;
            %And the players' last chance.
            elseif (c1==4 || c2==4 || c3==4 || c4==4 || c5==4)
                 a=rng;
                b1=rand(1,1);
                c1=ceil(b1*6);
                b2=rand(1,1);
                c2=ceil(b2*6);
                total4=c1+c2;
                finaltotal=total4;
            end;
        end;
    end;
    %Adding up all the times each total is earned
    if (finaltotal==2)
        tot2=tot2+1;
    end;
    if (finaltotal==3)
        tot3=tot3+1;
    end;
    if (finaltotal==4)
        tot4=tot4+1;
    end;
    if (finaltotal==5)
        tot5=tot5+1;
    end;
    if (finaltotal==6)
        tot6=tot6+1;
    end;
    if (finaltotal==7)
        tot7=tot7+1;
    end;
    if (finaltotal==8)
        tot8=tot8+1;
    end;
    if (finaltotal==9)
        tot9=tot9+1;
    end;
    if (finaltotal==10)
        tot10=tot10+1;
    end;
    if (finaltotal==11)
        tot11=tot11+1;
    end;
    if (finaltotal==12)
        tot12=tot12+1;
    end;
end;

%Compiling the data into one vector
fdat=dataset(tot2,tot3,tot4,tot5,tot6,tot7,tot8,tot9,tot10,tot11,tot12);
disp(fdat);
slice=fdat(2,:);

disp(slice);

At the end the bit about compiling works, but the slice bits do not. The only problem with fdat is that it also contains the variable names, so I can't graph it.

EDIT: I'm an idiot. If this ever happens to you just make a vector with each variable in one position, and then plot that.
« Last Edit: November 23, 2013, 01:54:25 pm by Zrk2 »
Logged
He's just keeping up with the Cardassians.

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5243 on: November 23, 2013, 04:30:24 pm »

Gah.
Code: [Select]
std::map< ColourRGBA, std::vector<SDL_Rect> > RectDrawQueue;

RectDrawQueue[ColourRGBA(255, 255, 255, 255)];
RectDrawQueue[ColourRGBA(255, 255, 255, 255)];
RectDrawQueue[ColourRGBA(255, 255, 255, 255)];
RectDrawQueue[ColourRGBA(255, 255, 255, 255)],

Creates four seperate vectors. std::map appears to be colourblind today.

Code: [Select]
struct ColourRGBA {
    Uint8 red;
    Uint8 blue;
    Uint8 green;
    Uint8 alpha;

    ColourRGBA() {;}

    ColourRGBA(int r, int g, int b, int a) {
        red = r; green = g; blue = b; alpha = a;
    }
};
This is ColourRGBA.

EDIT: And this is the comparison operator that std::map wants.

Code: [Select]
inline bool operator< (const ColourRGBA C1, const ColourRGBA C2) {
    if (C1.red < C2.red) return true;
    else if (C1.red != C2.red) return false;

    if (C1.blue < C2.blue) return true;
    else if (C1.blue != C2.blue) return false;

    if (C1.green < C2.green) return true;
    else if (C1.green != C2.green) return false;

    if (C1.alpha < C2.alpha) return true;
    else if (C1.alpha != C2.alpha) return false;
}
« Last Edit: November 23, 2013, 04:32:25 pm by cerapa »
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

MagmaMcFry

  • Bay Watcher
  • [EXISTS]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5244 on: November 23, 2013, 04:51:52 pm »


Okay, first of all, you can write that dice game a lot shorter, using vectors instead of scalars:
Code: [Select]
clear;
clc;

W = 2:12;
tot = 0.*W;
for i=1:1000
    finaltotal = 0;
    c = 1+floor(6*rand(1, 5));
    if(sum(c)>24)
        finaltotal = sum(c)-15;
    elseif(any(c==6))
        c(1:4) = 1+floor(6*rand(1, 4));
        if (sum(c(1:4))>17)
            finaltotal = sum(c(1:4))-9;
        elseif(any(c==5))
            c(1:3) = 1+floor(6*rand(1, 3));
            if (sum(c(1:3))>12)
                finaltotal = sum(c(1:3))-4;
            elseif(any(c==4))
                c(1:2) = 1+floor(6*rand(1, 2));
                finaltotal = sum(c(1:2));
            end
        end
    end
    tot = tot + (finaltotal==W);
end
dataset = [W;tot]
datasum = sum(tot)
Embrace the vectorness of this code, see how I use Matlab to modify many things at once.
Now the only other thing I changed from your code to mine is that I reset finaltotal to 0 before each loop, because that would make sense not to carry over values from the previous run, right?
Running this code results in something like this:

Code: [Select]
dataset =

     2     3     4     5     6     7     8     9    10    11    12
     5     4     2    12    15    23    12    77    74    44    26


datasum =

   294

It looks like most of the time none of your conditions apply, so the finaltotal actually remains 0, and the only reason you got seemingly valid results is because the value that was previously in finaltotal would be reused. Secondly, sometimes finaltotal gets set to values greater than 12 too. Looks like your algorithm is kinda messed up there. Could you maybe state the problem your program is supposed to solve?


Code: [Select]
inline bool operator< (const ColourRGBA C1, const ColourRGBA C2) {
    if (C1.red < C2.red) return true;
    else if (C1.red != C2.red) return false;

    if (C1.blue < C2.blue) return true;
    else if (C1.blue != C2.blue) return false;

    if (C1.green < C2.green) return true;
    else if (C1.green != C2.green) return false;

    if (C1.alpha < C2.alpha) return true;
    else return false;
}
Fixed that for you, the behaviour of your < operator was undefined if the colors actually happened to be equal.
Logged

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5245 on: November 23, 2013, 05:45:35 pm »

Fixed that for you, the behaviour of your < operator was undefined if the colors actually happened to be equal.
Can't believe I didn't notice that.

Thanks, works now.
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

Aptus

  • Bay Watcher
  • Indeed ôo
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5246 on: November 24, 2013, 01:50:24 pm »

So I got the database working thanks to the help from this thread but now I am at another conundrum, this time pertaining to ruby on rails. When googling I get "too much" information which is sometimes as unhelpful as too little. Basically the problem is simple but I am unused to the language.

I am a ruby on rails noob, I just decided to use it for this course because I wanted to learn it and it felt natural for this purpose. My problem is this.

In the handler for the products.html page I run a script that accesses my database and gets the item names that my "store" will "sell". (It will get amounts and costs as well but I just want to get something to work first). It stores this in an array/list/whatever it is called in ruby that I have named data.

Now I can easily parse this data using a simple "data.each do" statement but how do I actually get it to print on the website? And more importantly, do it dynamically, I can't just put a fixed length space on the website for the items since I at no time should have to know how many items I have in stock and hardcode my website for it.

I am not asking for a complete solution, just a pointer in the right direction would be helpful :)


Nevermind, I figured it out :p The things you can do with <% %> is amazing :p
« Last Edit: November 24, 2013, 04:00:47 pm by Aptus »
Logged

dragnar

  • Bay Watcher
  • [Glub]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5247 on: November 25, 2013, 12:18:17 am »

Well, unlikely as it is that this will turn up much, seems worth asking anyway: I'm working on a neural net, and at the moment it's 'learning' to... always output 1 for any and all datasets. Clearly, not what I want!

In theory, it's pretty simple. I've made a class for each node in the net, and getting the output of a node is as plain as it gets in machine learning algorithms:
Code: [Select]
float Node::output(){
  if(base){return baseOut;}

  float temp = 0;
  for(int i = 0;i<inputs.size();i++) {
    temp += inputs[i]->output()*weights[i];
  }
  return 1/(1+exp(-1*temp));
}
So yeah, just has a vector of nodes as it's inputs, and recursively works it's way to the start of the tree (where the base input nodes instead just return whatever input you gave them... Would be cleaner as a subclass, but it seemed somewhat silly to do that when all I needed was one flag on one function.) then applies a logistic function to the weighted sum of those outputs.

Learning is the tricky bit:
Code: [Select]
float Node::updateError(float real, float predicted, int ind){
  //Returns the node's error term multiplied by it's weight for index
  error = 0;
  if(!end){
    for(int i=0; i<outputs.size();i++){
      error += outputs[i]->updateError(real, predicted, index);
    }
    error = output()*(1-output()) * error;
  } else {
    error = predicted * (1-predicted) * (real - predicted);
  }
  for(int i=0; i<inputs.size();i++){
    if(ind == indexes[i]){
      return error * weights[i];
    }
  }
  return error;
}
void Node::updateWeights() {
  for(int i=0; i<inputs.size();i++){
    std::cout << weights[i] <<std::endl;
    weights[i] += trainingSpeed * error * inputs[i]->output();
    std::cout << weights[i] <<std::endl;
  }
This... isn't exactly my most elegant code, but I'm somewhat more concerned with getting this thing working so I can finish a research paper than anything else right now. >.> Ah well. Anyway, since the inputs don't learn, and they're connected to all nodes in the first layer, I just call updateError(whatever) on one of those and it updates all of them. Then updateWeights gets called for all nodes. As far as I can tell, this is exactly the algorithms used for backpropagation (checked multiple places, including wikipedia: http://en.wikipedia.org/wiki/Backpropagation) but... Yeah, as I said - the final output just ends up becoming 1.
Logged
From this thread, I learned that video cameras have a dangerosity of 60 kiloswords per second.  Thanks again, Mad Max.

Sergarr

  • Bay Watcher
  • (9) airheaded baka (9)
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5248 on: November 25, 2013, 01:44:21 am »

http://en.wikipedia.org/wiki/Backpropagation#Limitations

"The result may converge to a local minimum. The "hill climbing" strategy of gradient descent is guaranteed to work if there is only one minimum. However, oftentimes the error surface has many local minima and maxima. If the starting point of the gradient descent happens to be somewhere between a local maximum and local minimum, then going down the direction with the most negative gradient will lead to the local minimum.
Gradient descent can find the local minimum instead of the global minimum"

So basically backpropagation method is crap because it does not guarantee that it will converge to a desirable solution.
Logged
._.

dragnar

  • Bay Watcher
  • [Glub]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #5249 on: November 25, 2013, 05:09:38 am »

Oh, I'm perfectly aware of that flaw. But as I said - this is happening with any data set I put in, and the weights are initialized randomly. I can't imagine they just all happen to share the same exact local minimum... Though it is admittedly possible. My goal here isn't so much to find the optimal solution, as to prove that I can find a solution. (I can refine it from there as a follow-up project, but I feel like I have to be MISSING something obvious with this algorithm.)
Logged
From this thread, I learned that video cameras have a dangerosity of 60 kiloswords per second.  Thanks again, Mad Max.
Pages: 1 ... 348 349 [350] 351 352 ... 796