March Madness - Arduino on Unix |
This is an include file that will allow you to compile and run an Arduino sketch on Unix. Of course not everything is supported. This first pass only implements the Serial.print functions. However, that was a tremendous start and allowed me to run the eight queens program with practially no modification on MacOS command line and intel based linux.
Therefore this is actually more useful than the eight queens program itself and can be used in many Arduino programs.
On MacOS-X it took 1.25 seconds to finish, campare that to 6 minutes 31 seconds on the Arduino
Thats 312 times faster. 16 mhz * 312 = 4992 mhz = 4.9 ghz. The machine was 2.5 ghz dual core intel
based Mac. I am sure that the better than expected cpu speed is due to the word size.
How to use it.
//************************************************************************ //* Arduino on Unix library //* //* (C) 2010 by Mark Sproul //* Open source as per standard Arduino code //************************************************************************ //* this library (include file) allows you to compile and run SOME arduino programs //* on Unix without changing the entire program. It does that by implementing //* the hardware serial class and substituting the proper printf commands. //* This is expected to expand over time, //* for example, I would like to add the millis function call //************************************************************************ //* Edit history //************************************************************************ //* March 2, 2010 |
|
//************************************************************************ //* Eight Queens //* //* (C) 2010 by Mark Sproul //* Open source as per standard Arduino code //* http://obereed.net/queens/solution.html //************************************************************************ #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #include <inttypes.h> #define _COMPILE_FOR_UNIX_ #ifdef _COMPILE_FOR_UNIX_ #include "arduino_unix.h" #else #include "WProgram.h" #include "HardwareSerial.h" #endif unsigned long gChessBoard[8]; unsigned long gLoopCounter; int gValidCount; //************************************************************************ boolean CheckCurrentBoard(void) { int ii; int jj; int theRow; long theLongRow; long theLongColumns; int bitCount; //* we know we have 1 in each row, //* Check for 1 in each column theRow = 0; for (ii=0; ii<8; ii++) { theRow |= gChessBoard[ii]; } if (theRow != 0x0ff) { return(false); } //* we have 1 in each column, now check the diagonals theLongColumns = 0; for (ii=0; ii<8; ii++) { theLongRow = gChessBoard[ii] & 0x0ff; theLongRow = theLongRow << ii; theLongColumns |= theLongRow; } //* now count the bits bitCount = 0; for (ii=0; ii<16; ii++) { if ((theLongColumns & 0x01) == 0x01) { bitCount++; } theLongColumns = theLongColumns >> 1; } if (bitCount != 8) { return(false); } //* we now have to check the other diagonal theLongColumns = 0; for (ii=0; ii<8; ii++) { theLongRow = gChessBoard[ii] & 0x0ff; theLongRow = theLongRow << 8; theLongRow = theLongRow >> ii; theLongColumns |= theLongRow; } //* now count the bits bitCount = 0; for (ii=0; ii<16; ii++) { if ((theLongColumns & 0x01) == 0x01) { bitCount++; } theLongColumns = theLongColumns >> 1; } if (bitCount != 8) { return(false); } return(true); } //************************************************************************ boolean CheckForDone(void) { int ii; boolean weAreDone; int theRow; weAreDone = false; //* we know we have 1 in each row, //* Check for 1 in each column theRow = 0; for (ii=0; ii<8; ii++) { theRow |= gChessBoard[ii]; } if (theRow == 0x01) { weAreDone = true; } return(weAreDone); } //************************************************************************ void RotateQueens(void) { int ii; boolean keepGoing; int theRow; ii = 0; keepGoing = true; while (keepGoing && (ii < 8)) { theRow = gChessBoard[ii] & 0x0ff; theRow = (theRow >> 1) & 0x0ff; if (theRow != 0) { gChessBoard[ii] = theRow; keepGoing = false; } else { gChessBoard[ii] = 0x080; } ii++; } } //************************************************************************ void PrintChessBoard(boolean printSolutionNumber) { int ii; int jj; int theRow; char textString[32]; if (printSolutionNumber) { Serial.print("loop= "); Serial.print(gLoopCounter); Serial.print(" solution count= "); Serial.println(gValidCount); } // sprintf(textString, "LOOP= %ld", gLoopCounter); // Serial.println(textString); Serial.println("+----------------+"); for (ii=0; ii<8; ii++) { theRow = gChessBoard[ii]; Serial.print("|"); for (jj=0; jj<8; jj++) { if (theRow & 0x080) { Serial.print("Q "); } else { Serial.print(". "); } theRow = theRow << 1; } Serial.println("|"); } Serial.println("+----------------+"); Serial.println(); } //************************************************************************ void setup() { int ii; Serial.begin(9600); Serial.println(); Serial.println("Eight Queens brute force"); //* put the 8 queens on the board, 1 in each row for (ii=0; ii<8; ii++) { gChessBoard[ii] = 0x080; } Serial.println("The board starts out like this"); PrintChessBoard(false); gLoopCounter = 0; gValidCount = 0; } //************************************************************************ void loop() { gLoopCounter++; if (CheckCurrentBoard()) { gValidCount++; PrintChessBoard(true); } else if ((gLoopCounter % 1000) == 0) { // PrintChessBoard(); } RotateQueens(); if (CheckForDone()) { long elapsedSeconds; long elapsedMinutes; long elapsedHours; elapsedSeconds = millis() / 1000; elapsedMinutes = elapsedSeconds / 60; elapsedHours = elapsedMinutes / 60; Serial.println("----------------------------------"); Serial.println("All done"); Serial.print("Total itterations (boards) checked "); Serial.println(gLoopCounter); Serial.println("This is what the board ends up looking like"); PrintChessBoard(false); Serial.println("----------------------------------"); Serial.print("total seconds="); Serial.println(elapsedSeconds); Serial.print("hours="); Serial.println(elapsedHours); Serial.print("minutes="); Serial.println(elapsedMinutes % 60); Serial.print("seconds="); Serial.println(elapsedSeconds % 60); #ifdef _COMPILE_FOR_UNIX_ exit(0); #endif while (1); } } #ifdef _COMPILE_FOR_UNIX_ //************************************************************************ int main() { gStartTimeSeconds = time(&tloc); setup(); while (true) { loop(); } } #endif |