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
$102.42
Apple Inc.
+0.17
MSFT
$45.28
Microsoft Corpora
+0.40
GOOG
$569.86
Google Inc.
+0.66

MacTech Search:
Community Search:

Software Updates via MacUpdate

VueScan 9.4.41 - 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
Cloud 3.0.0 - File sharing from your men...
Cloud is simple file sharing for the Mac. Drag a file from your Mac to the CloudApp icon in the menubar and we take care of the rest. A link to the file will automatically be copied to your clipboard... Read more
LibreOffice 4.3.1.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
SlingPlayer Plugin 3.3.20.505 - Browser...
SlingPlayer is the screen interface software that works hand-in-hand with the hardware inside the Slingbox to make your TV viewing experience just like that at home. It features an array of... Read more
Get Lyrical 3.8 - Auto-magically adds ly...
Get Lyrical auto-magically add lyrics to songs in iTunes. You can choose either a selection of tracks, or the current track. Or turn on "Active Tagging" to get lyrics for songs as you play them.... Read more
Viber 4.2.2 - Send messages and make cal...
Viber lets you send free messages and make free calls to other Viber users, on any device and network, in any country! Viber syncs your contacts, messages and call history with your mobile device,... Read more
Cocktail 7.6 - General maintenance and o...
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
LaunchBar 6.1 - Powerful file/URL/email...
LaunchBar is an award-winning productivity utility that offers an amazingly intuitive and efficient way to search and access any kind of information stored on your computer or on the Web. It provides... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
BBEdit 10.5.12 - Powerful text and HTML...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more

Latest Forum Discussions

See All

Fire in the Hole Review
Fire in the Hole Review By Rob Thomas on August 29th, 2014 Our Rating: :: WALK THE PLANKUniversal App - Designed for iPhone and iPad Seafoam’s Fire in the Hole looks like a bright, 8-bit throwback, but there’s not enough booty to... | Read more »
Dodo Master Review
Dodo Master Review By Jordan Minor on August 29th, 2014 Our Rating: :: NEST EGGiPad Only App - Designed for the iPad Dodo Master is tough but fair, and that’s what makes it a joy to play.   | Read more »
Motorsport Manager Review
Motorsport Manager Review By Lee Hamlet on August 29th, 2014 Our Rating: :: MARVELOUS MANAGEMENTUniversal App - Designed for iPhone and iPad Despite its depth and sense of tactical freedom, Motorsport Manager is one of the most... | Read more »
Motorsport Manager – Beginner Tips, Tric...
The world of Motorsport management can be an unforgiving and merciless one, so to help with some of the stress that comes with running a successful race team, here are a few hints and tips to leave your opponents in the dust. | Read more »
Baseball Battle Review
Baseball Battle Review By Jennifer Allen on August 29th, 2014 Our Rating: :: SIMPLE HITTINGUniversal App - Designed for iPhone and iPad Simple and cute, Baseball Battle is a fairly fun baseball game for those looking for something... | Read more »
Checkmark 2.1 Update Released, and it’s...
Checkmark 2.1 Update Released, and it’s on Sale for a Limited Time Posted by Jessica Fisher on August 29th, 2014 [ permalink ] | Read more »
The Walking Dead Pinball Review
The Walking Dead Pinball Review By Blake Grundman on August 29th, 2014 Our Rating: :: DECISIONS, DECISIONS...Universal App - Designed for iPhone and iPad Zen Studios is at it again, taking a property that would never seem to work... | Read more »
Stupeflix Has Released a Major Update fo...
Stupeflix Has Released a Major Update for Replay Posted by Jessica Fisher on August 29th, 2014 [ permalink ] iPhone App - Designed for the iPhone, compatible with the iPad | Read more »
ALONE… Review
ALONE… Review By Jennifer Allen on August 29th, 2014 Our Rating: :: MINIMALISTIC AND TOUGHUniversal App - Designed for iPhone and iPad Tough yet satisfying, ALONE… is a challenging endless flyer with some suitably sensitive... | Read more »
Hyperlapse Review
Hyperlapse Review By Jennifer Allen on August 28th, 2014 Our Rating: :: SPEEDY VIDEO SNAPSUniversal App - Designed for iPhone and iPad Want to make a great time-lapse video quickly? Hyperlapse is perfect for that.   | Read more »

Price Scanner via MacPrices.net

13-inch 1.4GHz MacBook Air on sale for $899,...
Adorama has the new 2014 13″ 1.4GHz/128GB MacBook Air on sale for $899.99 including free shipping plus NY & NJ tax only. Their price is $100 off MSRP. Read more
It’s Official: Apple Issues Invitations To Se...
Apple has issued one of its characteristically cryptic press invitations for a special event to be held at the Flint Center for the Performing Arts in hometown Cupertino on Sept. 9, 2014 at 10:00 am... Read more
Tablet Shipments To See First On-year Decline...
TrendForce analyst Caroline Chen notes that when the iPad launched in 2010, it was an instant hit and spurred a tablet PC revolution, with tablets so popular that that notebook PC sales stagnated and... Read more
SOBERLINK Releases Apple iOS Compatible Handh...
Cypress, California based SOBERLINK, Inc., creator of the first handheld Breathalyzer designed to improve recovery outcomes, continues to show prominence in the mobile alcohol monitoring space with... Read more
New 21″ 1.4GHz iMac on sale again for $999, s...
Best Buy has the new 21″ 1.4GHz iMac on sale for $999.99 on their online store. Their price is $100 off MSRP. Choose free shipping or free local store pick up. Price is for online orders only, in-... Read more
Smartphone Outlook Remains Strong for 2014, U...
According to a new mobile phone forecast from the International Data Corporation (IDC) Worldwide Quarterly Mobile Phone Tracker, more than 1.25 billion smartphones will be shipped worldwide in 2014,... Read more
Save up to $60 with Apple refurbished iPod to...
The Apple Store has Apple Certified Refurbished 5th generation iPod touches available starting at $149. Apple’s one-year warranty is included with each model, and shipping is free. Many, but not all... Read more
12-Inch MacBook Air Coming in 4Q14 or 2015 –...
Digitimes’ Aaron Lee and Joseph Tsai report that according to Taiwan-based upstream supply chain insiders, Apple plans to launch a thinner MacBook model either at year end 2014 or in 2015, and that... Read more
Sapphire Screen “Most Wanted” iPhone 6 New Fe...
According to the ‘uSell.com iPhone Most Wanted Survey’ — a representative survey of 1,000 U.S. smartphone users conducted by used iPhone marketplace uSell.com — close to half of all smartphone users... Read more
The iPad’s Real Competitive Challenger (Not S...
It’s been my contention for some time that the iPad is suffering from something of an identity crisis, and I suspect that may be a factor in slackening sales this year. Apple can’t seem to decide... 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...
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...
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
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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.