TweetFollow Us on Twitter

Jul 96 Challenge
Volume Number:12
Issue Number:7
Column Tag:Programmer’s Challenge

Programmer’s Challenge

By Bob Boonstra

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

Connect IV

This month, your Challenge is to write code for a well-known game that will compete against other Challenge entries, as well as against the clock. The game board consists of an NxM array into which two players alternate inserting pieces. Pieces are inserted into the top of a column in the vertically oriented board, so that they drop into the lowest unoccupied cell of that column. The objective is to be the first player to arrange 4 or more pieces into a vertical, horizontal, or diagonal line.

The winner of this Challenge will be determined by a round-robin tournament in which each entry competes against each other entry an even number of times, half of the time playing with the first move, and half playing with the second move. (If the number of entries makes a full round-robin tournament impractical, I’ll use another fair tournament scheme.) Each tournament victory will earn two points for the winning entry, and each tie earns one point. The entry with the greatest number of tournament points wins the Challenge. Ties will be broken by execution time, code size, etc.

The prototype for the code you should write is:

long /*yourMove*/ ConnectMove (
 long numCols,   /* number of columns in the game board */
 long numRows,   /* number of rows in the game board */
 void *privStorage,/* preallocated storage for your use */
 long prevMove,  /* column where opponent last moved, 0 ..  numCols-1 */
 Boolean newGame,/* TRUE if this is your first move in a new game */
 Boolean *victory/* set to TRUE if you claim victory */
    /*   this move, otherwise set to FALSE */
);

For your first move in a new game, your ConnectMove code will be called with newGame set to TRUE. If your opponent made the first move in this game, prevMove will be set to the (origin zero) column that the opponent selected as the first move. If you are to make the first move, prevMove will be set to -1. In the call for the first move of a new game, you will also be provided with a pointer privStorage to 1MB of memory, already initialized to zero, for your use during that game. Finally, the initial call will provide the number of columns (numCols) and rows (numRows) in the board for that game. The number of rows and columns will each be larger than 6 and less than 64.

Alternating calls will be made to your ConnectMove routine and the opposing ConnectMove routine. For the second and subsequent moves in each game, newGame will be set to FALSE, and the values of numCols, numRows, and privStorage will be the same as in the initial call. Each time ConnectMove is called, you should evaluate the move made by your opponent (provided in prevMove) and return the column into which you make your move as the function result. If you believe you have won the game, you should set *victory to TRUE; otherwise you should set *victory to FALSE. Falsely claiming victory or making an illegal move, such as trying to insert a game piece into a column that is already filled, will result in forfeiting that game.

For this Challenge, you may dynamically allocate additional storage beyond that provided by privStorage, provided you deallocate it before returning after each move. You may not use any static storage beyond that provided by privStorage.

To conduct the tournament, the code for multiple entries will be compiled into a single application. In case you are wondering, I will append a unique integer to the name of each routine before compiling so that each ConnectMove routine will be named uniquely.

This will be a native PowerPC Challenge, scored using the Symantec environment. Solutions may be coded in C or C++.

Two Months Ago Winner

Perhaps the earlier Challenge deadline caught people a little off guard this month. Whatever the reason, only three people chose to enter the Edge Detector Challenge this month. Congratulations to Ernst Munter (Kanata, ON, Canada) for submitting the fastest entry to the Edge Detector Challenge. This is Ernst’s third win in the last four contests, and it brings him within 2 points of the lead in our Top Contestants point total.

Contestants were required to process PixMap images in 8-bit, 16-bit, or 32-bit color and identify pixels where the color difference with adjacent pixels exceeded a specified threshold in the specified color component (or combination of components). The second place solution by Miguel Cruz Picao was actually faster than the winning solution in two of the three color depth cases, but was slower in the third case and slower overall. Miguel elected to implement entirely separate code for each of the three color depth cases, while Ernst sacrificed some processing time for smaller code size by testing for color depth while processing each line of the image, using common code for the rest of the three cases. On the other hand, Ernst used the EdgeType provided as a parameter to select, outside of any loops, the edge detection routine to use for the entire image, while Miguel’s code tested the EdgeType for each pixel. Ernst elected to make four passes through each pair of adjacent image lines, comparing pixels that were adjacent horizontally, diagonally in each direction, and vertically, allowing compact and efficient comparison loops. The overall result was that the winning solution was some 25% faster than the second-place solution in the 32-bit case, which was enough to make it about 5% faster overall.

Table 1 summarizes the results for each entry, including code size, data size, execution time for each of the three color depth cases, and the overall score based on total execution time. Numbers in parentheses after a person’s name indicate that person’s cumulative point total for all previous Challenges, not including this one.

Name Code Data Time Time Time Score

(32) (16) (8)

Ernst Munter (154) 1492 116 833 912 723 2467

Miguel Cruz Picao (11) 3420 20 1120 899 582 2600

Greg Cooper 1872 28 1830 1902 1802 5534

Table 1. Results for each entry

Rank Name Points Rank Name Points

1. [Name deleted] 176 11. Mallett, Jeff 44

2. Munter, Ernst 174 12. Kasparian, Raffi 42

3. Gregg, Xan 92 13. Vineyard, Jeremy 42

4. Karsh, Bill 90 14. Lengyel, Eric 40

5. Larsson, Gustav 87 15. Darrah, Dave 31

6. Stenger, Allen 65 16. Brown, Jorg 30

7. Cutts, Kevin 57 17. Lewis, Peter 30

8. Riha, Stepan 51 18. Landry, Larry 29

9. Goebel, James 49 19. Beith, Gary 24

10. Nepsund, Ronald 47 20. Elwertowski, Tom 24

Table 2. Top 20 contestants

Top 20 Contestants of All Time

Table 2 shows the Top 20 Contestants for the Programmer’s Challenges to date The numbers below include points awarded for this month’s entrants.

There are three ways to earn points: (1) scoring in the top 5 of any Challenge, (2) being the first person to find a bug in a published winning solution or, (3) being the first person to suggest a Challenge that I use. The points you can win are:

1st place 20 points 5th place 2 points

2nd place 10 points finding bug 2 points

3rd place 7 points suggesting Challenge 2 points

4th place 4 points

Here is Ernst’s winning solution:

EdgeDetector.c

Copyright 1996, Ernst Munter

/*
Problem Statement
---------
Given a Pixmap image, create a Bitmap which shows the edges in the image.

Pixmaps may have 8, 16, or 32 bit colors. Parameters control which colors should contribute to the edge 
detection, and a threshold for the color space difference (an RMS value) to be considered an edge.

All 16 bits of the individual color values must be considered, which can result in 32-bit overflow when squares 
are added.

Solution
----
The general idea is to process 2-row strips of the image through an intermediate ColorSpec stage in which 
the “value” fields are used to mark edge pixels. 

Step1:

We allocate a small amount of memory, sufficient to hold two rows of pixels in ColorSpec format (8 bytes 
per pixel). Pixels from each row in the Pixmap are converted to ColorSpec format (RGB + “value”).

Step2:

The two lines are scanned with 4 different patterns to determine edges:  given 2 rows with pixels as shown

 A B C D E F G H ...
 a b c d e f g h ...

We compare pixel pairs in four separate runs of EdgePairs():
 a-b, b-c, c-d, d-e ...  (WEST - EAST)
 A-b, B-c, C-d, D-e ...  (NORTH-WEST - SOUTH-EAST)
 B-a, C-b, D-c, E-d ...  (NORTH-EAST - SOUTH-WEST)
 A-a, B-b, C-c, D-d ...  (NORTH - SOUTH)

This procedure is repeated for rows 0 and 1, then 1 and 2, 2 and 3, and so on.  (Plus an West-East run for 
row 0).

During each run, the “value” field of every pair of pixels found to be part of an edge is set to -1 (0xFFFF). 
All other values remain at 0.

Step 3:

Before shifting down to the next row, the ColorSpecs of the upper row are scanned to construct a row of 
the Bitmap.

Optimizations
-------
The combinations of pixel size and edge types are dealt with as follows:

All pixel types are normalized to a single ColorSpec format by the GetLine procedure.

Different edge types call for different series of tests.  Specifically, 1, 2, or 3 colors can be optimized separately. 
On of a set of 7 separate short functions is selected at runtime.  This requires the edge type to be evaluated 
only once, to select the EdgeXXX procedure that will be used many times as the image is scanned from top 
to bottom.

Comparing an RMS (root of sum of squares) value with a threshold is equivalent to comparing the sum of 
squares with the square of the threshold value.  This avoids the need to compute square roots.

In the case of a single color edge type, the square of the difference would not need to be formed.  A simple 
comparison of the threshold with the absolute difference would suffice.  However, the runtime difference 
between a multiply and computing the absolute value would depend on CPU type etc, and would tend to be 
small.  I opted for uniformity, and square all differences.

The dynamically allocated storage should typically fit inside the CPU cache, and not slow things down as 
it is read and written continuously.

Assumptions
------
Bitmap is large enough to hold the result.  eType is within the range of redOnly to redGreenAndBlue, otherwise 
the call will certainly crash.

Amount of static memory = 8 pointers (32 bytes)
Amount of dynamic memory required is for 2 rows of
ColorSpec records (a 1024 pix wide image -> 16K of storage).

*/

#include <QDOffscreen.h>
// Contains PixMap, BitMap and EdgeType defs

#include <stdlib.h>

Definitions
typedef enum
{
 redOnly = 1,
 greenOnly,
 redAndGreen,
 blueOnly,
 redAndBlue,
 greenAndBlue,
 redGreenAndBlue
} EdgeType;

typedef void EdgeProc(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

Function Prototypes
void EdgeDetect(
 PixMapHandle    pMapH,
 BitMap *bMap,
 unsigned short  threshold,
 EdgeType eType);

void Get1Line(
 ColorSpec* line,
 void*  pix,
 int    size,
 ColorSpec* CT,
 int    pixelSize);

void EdgeRed(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

void EdgeGreen(
 ColorSpec* P,
 ColorSpec*    Q,
 int    size,
 unsigned long   TH);

void EdgeRedGreen(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

void EdgeBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

void EdgeRedBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

void EdgeGreenBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

void EdgeRedGreenBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH);

void Copy2Bitmap(
 ColorSpec* P,
 unsigned char*  bits,
 int    size);

Static Allocations
static EdgeProc* EdgeProcedure[8] = {
 0,
 EdgeRed,
 EdgeGreen,
 EdgeRedGreen,
 EdgeBlue,
 EdgeRedBlue,
 EdgeGreenBlue,
 EdgeRedGreenBlue};

EdgeDetect
void EdgeDetect(
 PixMapHandle    pMapH,
 BitMap *bMap,
 unsigned short  threshold,
 EdgeType eType) {
PixMap* pm=*pMapH;

unsigned char*   pix=(unsigned char*)GetPixBaseAddr(pMapH);
unsigned char*   bits=(unsigned char*)bMap->baseAddr;
unsigned long  TH=(unsigned long)threshold*threshold;
int     y;
int     pixelSize=pm->pixelSize;
int     pixRowBytes=pm->rowBytes & 0x3FFF;
int     pixInRow=pm->bounds.right-pm->bounds.left;
int     bitRowBytes=bMap->rowBytes;

ColorSpec*  allocated;
ColorSpec*  line0;
ColorSpec*  line1;
ColorSpec*  CTable=(*(pm->pmTable))->ctTable;
EdgeProc* EP;

// Get memory for a 2-row strip of pixels:
  if (0==(allocated=(ColorSpec*)malloc(
 2*sizeof(ColorSpec)*pixInRow))) return;
  line0=allocated-1;  //(we always use pre-increment later)
  line1=line0+pixInRow;

// Determine EdgeProc to use:
  EP=EdgeProcedure[eType];

// Prepare first row:
  Get1Line(line0,pix,pixInRow,CTable,pixelSize);
  (*EP)(line0,line0+1,pixInRow-1,TH);    //W-E

// Process remaining rows:
  for (y=pm->bounds.top+1;y<pm->bounds.bottom;y++) {
    pix+=pixRowBytes;
    Get1Line(line1,pix,pixInRow,CTable,pixelSize);
                                                             
    (*EP)(line1,  line1+1,pixInRow-1,TH);  //W-E
    (*EP)(line0,  line1+1,pixInRow-1,TH);  //NW-SE
    (*EP)(line0+1,line1,  pixInRow-1,TH);  //NE-SW
    (*EP)(line0,  line1,  pixInRow,TH);    //N-S

// Convert ColorSpec.values to Bitmap.bits:
    Copy2Bitmap(line0,bits,bitRowBytes);

// Swap line0 with line1:
    {ColorSpec* temp=line0;line0=line1;line1=temp;}
    bits+=bitRowBytes;
  }

// Convert the last row;
  Copy2Bitmap(line0,bits,bitRowBytes);

// Release dynamic memory:
  free(allocated);
}

Get1Line
/***************** Local Functions ************************/
void Get1Line(
 ColorSpec* line,
 void*  pix,
 int    size,
 ColorSpec* CT,
 int    pixelSize){
inti,r,g,b;
unsigned long  x;
  if (pixelSize==8) {
    unsigned char*   PIX =((unsigned char*)pix);
    for (i=0;i<size;i++) {
      x=*PIX++;
      line++;
      *((double*)(line))=*((double*)(CT+x));
      line->value=0;
    }
  } else if (pixelSize==16) {
    unsigned short*  PIX =((unsigned short*)pix);
    for (i=0;i<size;i++) {
      x=*PIX++;
      line++;
      r=((x & 0x7C00) << 1)  | ((x & 0x7C00) >> 4) |
 ((x & 0x7C00) >> 9)  | ((x & 0x7C00) >> 14);
      g=((x & 0x03E0) << 6)  | ((x & 0x03E0) << 1) |
 ((x & 0x03E0) >> 4)  | ((x & 0x03E0) >> 9);
      b=((x & 0x001F) << 11) | ((x & 0x001F) << 6) |
 ((x & 0x001F) << 1)  | ((x & 0x001F) >> 4);
      line->value=0;
      line->rgb.red=  (unsigned short)r;
      line->rgb.green=(unsigned short)g;
      line->rgb.blue= (unsigned short)b;
    }
  } else { //pixelSize not 8 or 16, so it must be 32
    unsigned long* PIX =((unsigned long*)pix);
    for (i=0;i<size;i++) {
      x=*PIX++;
      line++;
      r=((x & 0xFF0000) >> 8) | ((x & 0xFF0000) >> 16);
      g= (x & 0x00FF00)       | ((x & 0x00FF00) >> 8);
      b= (x & 0x0000FF)       | ((x & 0x0000FF) << 8);
      line->value=0;
      line->rgb.red=  (unsigned short)r;
      line->rgb.green=(unsigned short)g;
      line->rgb.blue= (unsigned short)b;
    }
  }
}

Copy2Bitmap
void Copy2Bitmap(
 ColorSpec* P,
 unsigned char*  bits,
 int    size) {
int     i;
  P++;
  for (i=0;i<size;i++) {
    *bits = (unsigned char) (
     (P[0].value & 0x80) |
     (P[1].value & 0x40) |
     (P[2].value & 0x20) |
     (P[3].value & 0x10) |
     (P[4].value & 0x08) |
     (P[5].value & 0x04) |
     (P[6].value & 0x02) |
     (P[7].value & 0x01) );
    P+=8;
    bits++;
  }
}

EdgeRedGreenBlue
void EdgeRedGreenBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  delta,acc;
  for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.red-Q->rgb.red;
    acc*=acc;
    delta=(unsigned long)P->rgb.green-Q->rgb.green;
    delta*=delta;
    acc+=delta;
    if (acc<delta) {P->value=Q->value=-1;continue;}
    delta=(unsigned long)P->rgb.blue-Q->rgb.blue;
    delta*=delta;
    acc+=delta;
    if ((acc>=TH) || (acc<delta)) P->value=Q->value=-1;
  }
}

EdgeGreenBlue
void EdgeGreenBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  delta,acc;
  for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.green-Q->rgb.green;
    acc*=acc;
    delta=(unsigned long)P->rgb.blue-Q->rgb.blue;
    delta*=delta;
    acc+=delta;
    if ((acc>=TH) || (acc<delta)) P->value=Q->value=-1;
  }
}


EdgeRedBlue
void EdgeRedBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  delta,acc;
  for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.red-Q->rgb.red;
    acc*=acc;
    delta=(unsigned long)P->rgb.blue-Q->rgb.blue;
    delta*=delta;
    acc+=delta;                                    
    if ((acc>=TH) || (acc<delta)) P->value=Q->value=-1;
  }
}

EdgeRedGreen
void EdgeRedGreen(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  delta,acc;
   for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.red-Q->rgb.red;
    acc*=acc;
    delta=(unsigned long)P->rgb.green-Q->rgb.green;
    delta*=delta;
    acc+=delta;
    if ((acc>=TH) || (acc<delta)) P->value=Q->value=-1;
  }
}

EdgeBlue
void EdgeBlue(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  acc;
  for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.blue-Q->rgb.blue;
    acc*=acc;
    if (acc>=TH) P->value=Q->value=-1;
  }
}

EdgeGreen
void EdgeGreen(
 ColorSpec* P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  acc;
  for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.green-Q->rgb.green;
    acc*=acc;
    if (acc>=TH) P->value=Q->value=-1;;
  }
}

EdgeRed
void EdgeRed(
 ColorSpec*    P,
 ColorSpec* Q,
 int    size,
 unsigned long   TH) {
int     i;
unsigned long  acc;
  for (i=0;i<size;i++) {
    P++;Q++;
    acc=(unsigned long)P->rgb.red-Q->rgb.red;
    acc*=acc;
    if (acc>=TH) P->value=Q->value=-1;
  }
}

 
AAPL
$99.18
Apple Inc.
-1.57
MSFT
$45.90
Microsoft Corpora
-0.46
GOOG
$568.27
Google Inc.
-9.09

MacTech Search:
Community Search:

Software Updates via MacUpdate

Cocktail 8.0 Beta 2 - General maintenanc...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
QuickBooks 2015 16.0.0.1352 R1 - Financi...
QuickBooks 2015 helps you manage your business easily and efficiently. Organize your finances all in one place, track money going in and out of your business, and spot areas where you can save.... Read more
Mac DVDRipper Pro 5.0.1 - Copy, backup,...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
Apple OS X bash Update 1.0 - Fix for sec...
The OS X bash Update fixes a security flaw in the bash UNIX shell on OS X 10.9.5 (also on OS X 10.8 and 10.7 [see Related Links below]). OS X 10.9.5 or later Downloads for OS X 10.8 and OS X 10.7 in... Read more
SyncTwoFolders 2.0.5 - Syncs two user-sp...
SyncTwoFolders simply synchronizes two folders. It supports synchronization across mounted network drives and it is a possibility to run a simulation showing in a log what will be done. Please visit... Read more
FinderPop 2.5.7 - Classic Mac utility, n...
FinderPop is a Universal preference pane that extends OS X's contextual menus using a FinderPop Items folder much as the Apple Menu Items folder used to do for the Apple menu. It has other features... Read more
VueScan 9.4.45 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
LibreOffice 4.3.2.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
calibre 2.4 - Complete e-library managem...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital... Read more
Default Folder X 4.6.9b1 - Enhances Open...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more

Latest Forum Discussions

See All

iKeywi - Customizable 5-Row Keyboard (U...
iKeywi - Customizable 5-Row Keyboard 1.0 Device: iOS Universal Category: Utilities Price: $.99, Version: 1.0 (iTunes) Description: Want to add an extra row to your iPhone/iPad? One of the most popular keyboard extension in iOS... | Read more »
Manage Your Cloud – Wunderlist Now Suppo...
Manage Your Cloud – Wunderlist Now Supports Dropbox Posted by Jessica Fisher on October 1st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Nexticy Review
Nexticy Review By Jennifer Allen on October 1st, 2014 Our Rating: :: IDEAL FORM CREATIONiPad Only App - Designed for the iPad Nexticy allows you to make your own forms for research purposes or to organize your business better. It’s... | Read more »
Tiny Troopers: Alliance Marches onto the...
Tiny Troopers: Alliance Marches onto the App Store Tomorrow Posted by Jessica Fisher on October 1st, 2014 [ permalink ] Tiny Troopers: Alliance, by Kukouri, is a | Read more »
HeroCraft Introduces Unlimited Sequel to...
HeroCraft Introduces Unlimited Sequel to WW2: Sandbox. Strategy & Tactics Posted by Jessica Fisher on October 1st, 2014 [ permalink ] | Read more »
RGB Express Review
RGB Express Review By Jennifer Allen on October 1st, 2014 Our Rating: :: DELIGHTFUL PUZZLINGUniversal App - Designed for iPhone and iPad Guide trucks along their delivery routes in RGB Express, a testing but charming puzzle game... | Read more »
The Sagas of Fire*Wolf (Games)
The Sagas of Fire*Wolf 1.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0 (iTunes) Description: | Read more »
BuggyFun Review
BuggyFun Review By Amy Solomon on October 1st, 2014 Our Rating: iPad Only App - Designed for the iPad BuggyFun allows children to create their own tracks for bugs to interact with for a unique open-ended experience.   | Read more »
Fold the Adventure Review
Fold the Adventure Review By Jennifer Allen on October 1st, 2014 Our Rating: :: AWKWARD FOLDSUniversal App - Designed for iPhone and iPad Fold pieces of paper to create platforms for a princely rabbit in this puzzle game; something... | Read more »
WW2: Sandbox. Strategy & Tactics (G...
WW2: Sandbox. Strategy & Tactics 1.0.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0.0 (iTunes) Description: ***NOTE: Compatible with iPhone 4s and up, iPad 2 and up - may not work properly on earlier devices... | Read more »

Price Scanner via MacPrices.net

Amazon offers 13-inch MacBook Air for $899, $...
Amazon.com has the 13″ 1.4GHz 128GB MacBook Air on sale for $100 off MSRP including free shipping: - 13″ 1.4GHz 128GB MacBook Air: $899.99 Read more
Apple resting On Its iPhone Laurels? – The ‘B...
Apple calls its new iPhone 6 and 6 Plus “The Biggest Advancements in iPhone History,” but does reality live up to the hype? “Seldom have so many waited so breathlessly for so little,” tweeted veteran... Read more
Roundup of Apple Mac and iPad Education disco...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more
Apple Boycotts German Magazine Computer Bild...
Apple has revoked its PR accreditation of Germany’s Computer Bild, Europe’s best-selling PC magazine, in reaction to Bild’s posting of a “#Bentgate” YouTube video. Axel Telzerow, editor in chief of... Read more
iPhone 6 & iPhone 6 Plus Available in Chi...
Apple has announced that iPhone 6 and iPhone 6 Plus will be available in China beginning Friday, October 17 from the Apple Online Store (http://www.apple.com), Apple’s retail stores, and an expansive... Read more
MacBook Airs on sale for $100 off MSRP, start...
Best Buy has the new 2014 MacBook Airs on sale for $100 off MSRP on their online store. Choose free home shipping or free local store pickup (if available). Prices valid for online orders only, in-... Read more
Apple Releases OS X Mavericks bash Update 1.0...
Apple has released a patch update for OS X Mavericks users to address the recently-detected “Shellshock” security bug in BSD UNIX’s bash shell. Apple says only a few Mac users who had manually... Read more
Pivotal Payments Ready for Apple Pay – FlexPo...
Pivotal Payments, a provider of merchant services and global payment processing solutions, has announced its proprietary FlexPoint platform will support credit and debit transactions through Apple’s... Read more
iStabilizer Announces Tabarm — First Friction...
iStabilizer, a specialist in universal lightweight compact tripods, steady cams, dollies, mounts, and remotes for smartphones, tablets, and cameras, announced today the iStabilizer tabArm, the first... Read more
IStabilizer Flex Smartphone Tripod Wins Usa T...
iStabilizer, a specialist in universal lightweight compact tripods, steady cams, and other products for smartphones, tablets, and cameras, has announced today that its iStabilizer Flex smartphone... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.