TweetFollow Us on Twitter

Aug 93 Challenge
Volume Number:9
Issue Number:8
Column Tag:Programmers’ Challenge

Programmers’ Challenge

By Mike Scanlin, MacTech Magazine Regular Contributing Author

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

REPLACE ALL

Have you ever done a Replace All operation in some program and thought that it was taking more time than it should to do the job? Well, this month you’ll have your chance to show those text-based applications how to do it right. The goal is to write a case-sensitive find and replace function.

The prototype of the function you write is:

long ReplaceAll(sourceHndl, 
 replaceHndl, targetHndl)
Handle  sourceHndl;
Handle  replaceHndl;
Handle  targetHndl;

The sourceHndl contains the text to search for. The replaceHndl contains the text to replace the source text with, once found, and the targetHndl contains the text to look in. You should replace each occurance of the sourceHndl text in targetHndl with the replaceHndl text. You can get the sizes of each piece by using GetHandleSize. And you can resize targetHndl as necessary with normal Mac memory manager calls.

For example, suppose targetHndl contained this text:

Perhaps this modern sorcery especially attracts those who believe in 
happy endings and fairy godmothers.

with this sourceHndl text:

fairy godmothers

and this replaceHndl text:

pink elephants

After a call to ReplaceAll targetHndl would contain:

Perhaps this modern sorcery especially attracts those who believe in 
happy endings and pink elephants.

The return value from ReplaceAll is the actual number of substitutions made (1 in this example). You must find an exact match before doing a replacement (i.e. ‘cat’ != ‘Cat’). The max size of each Handle on entry to ReplaceAll will be 255 bytes for sourceHndl and replaceHndl; and 65535 bytes for targetHndl. There is no max output size for targetHndl. You should grow or shrink targetHndl as necessary so that it’s exactly the correct size when ReplaceAll returns. If you run out of memory while trying to grow targetHndl then return -1 instead of the number of substitutions. The text you will be searching through will be mixed case English text containing punctuation.

TWO MONTHS AGO WINNER

Congratulations to Bob Boonstra (Westford, MA) for his fast and small entry in the Where In The World challenge. Tying Bob for speed but not for code size is Jeff Mallett (Hickory, NC). Jeff’s solution was a little faster than Bob’s for some cases and a little slower than Bob’s for others. I couldn’t find a pattern so I went to the second criteria, code size, to pick the winner.

Here are the sizes and times for the 16 entries that yielded correct results:

Name bytes ticks

Bob Boonstra 358 55

Jeff Mallett 728 55

Stepan Riha 514 78

Jim Bumgardner 454 86

Jeff Tupper 624 94

Russ LaValle 530 101

Jan Bruyndonckx 402 112

David Salmon 638 133

Ted Krovetz 250 136

Patrick Breen 350 137

Ricky Schrieber 286 145

Thomas Studer 488 164

Stuart McIntosh 390 230

Robert Fisher 396 268

David Rand 302 420

Bob Menteer 1224 506

Since the puzzle stated that exact matches would be passed to FindCity 2/3rds of the time it is reasonable to do an exact match search first, before starting off and trying to find the five closest matches. Bob makes this first pass by comparing the first 4 bytes of the target string with the first 4 bytes of each element in the cities array. Only if there is an exact match (which includes the length byte) does he then continue to check the remaining parts of the string (again, 4 bytes at a time through clever typecasting).

Once Bob detects that he doesn’t have an exact match, he calculates a closeness-of-match number for every entry in the cities array. But he eliminates some of the work by first comparing the difference in length bytes between the target string and the current element. If it’s greater than his current largest difference (of the 5 closest he’s keeping track of) then he skips the element completely and moves on to the next. This is a neat trick that takes advantage of the way the closeness-of-match number was defined. I like it.

Here’s Bob’s winning solution:

/* FindCity by Bob Boonstra */
 
#define kMax5
#define kSentinal0x035A5A5A
#define low3Bytes0x00FFFFFF
 
typedef struct distRec {
 short  theDist;
 unsigned short  theIndx;
} distRec;

Boolean FindCity(cityNames, cityToFindNamePtr, 
 closestMatches)
Str255  cityNames[];
Str255  *cityToFindNamePtr;
unsigned short closestMatches[];
{
 distRectheRec[kMax];
 unsigned char   *curCityP, *city2Find;
 unsigned short  curIndx;
 register short  maxDist;
  
 city2Find = *cityToFindNamePtr;
 curCityP = cityNames[0];
 /*
  *Scan for an exact match.
  */
 {
 register long toFind3;

 curIndx = 0;
 toFind3 = *(long *)city2Find & low3Bytes;
 do {
 if ( *(long *)curCityP == *(long *)city2Find ) {
 /*
  *If first 4 characters match, look at the
  *rest in chunks of 4 characters.
  */
 register short charsLeft;
 register unsigned char *s1 = curCityP+4;
 register unsigned char *s2 = city2Find+4;

 if ( (charsLeft = *curCityP-7) >= 0 ) {
 do {
 if ( *(long *)s1 != *(long *)s2 )
 goto nextOne;
 s1 += 4;  s2 += 4;
 } while ( (charsLeft-=4) >= 0 );
 }
 /*
  *If all chunks of 4 characters match, look at the
  *rest individually.
  */
 if (charsLeft+=4) {
 do {
 if (*s1++ != *s2++)
 goto nextOne;
 } while (--charsLeft);
 }
 /*
  *Exact match found.  Return index of match.
  */
 closestMatches[0] = curIndx;
 return(1);
 /*
  *Process the next city. Exit if it is greater in
  *alphabetic order (based on 1st 3 characters,
  *w/o length byte).
  *Sentinal will force exit if necessary.
  */
 nextOne: ;
 }

 ++curIndx;
 curCityP+=sizeof(Str255);

 }  while ( (*(long *)curCityP & low3Bytes) <= toFind3 );
 }
 /*
  *Initialize distance structure for 5 closest matches.
  */
 noMatch:
 {
 register distRec *p = &theRec[0];

 (++p)->theDist = (++p)->theDist = (++p)->theDist =
 (++p)->theDist = (p)->theDist = maxDist = 255;
 }
 /*
  *Loop thru cityNames to find closest matches.
  */
 curCityP=cityNames[0];
 curIndx=0;
 do {
 register short curDist;
 /*
  *Calculate dist between cityToFind and cityName[curIndx].
  */
 {
 register unsigned char *s1,*s2;
 register short lng;

 /*initialize dist to length difference */
 s2 = city2Find;
 lng = *s2++;
 if ((curDist = *(s1=curCityP) - lng) < 0) {
 curDist = -curDist;
 lng = *s1;
 }
 /*
  *Move to next city if distance exceeds the distance
  *of 5 other cities.
  *Increment dist for each nonMatching char.
  *Unroll for a little extra speed.
  */
 ++s1;
 do {
 if (*s1++ != *s2++)
 if (++curDist >= maxDist) goto nextCity;
 if (!(--lng)) break;
 if (*s1++ != *s2++)
 if (++curDist >= maxDist) goto nextCity;
 if (!(--lng)) break;
 if (*s1++ != *s2++)
 if (++curDist >= maxDist) goto nextCity;
 if (!(--lng)) break;
 if (*s1++ != *s2++)
 if (++curDist >= maxDist) goto nextCity;
 } while (--lng);
 }
 /*
  *This city is closer than at least one of the five
  *currently closest cities.  Store the distance and
  *the index in the proper place.
  *distRec[0].theIndx is the closest match, and
  *distRec[0].theDist is the associated distance
  */
 {
 register distRec *q=theRec+kMax-1;

 maxDist=curDist;
 if (curDist >= (q-1)->theDist) goto storeIt;
 *q = *(q-1);
 maxDist = q->theDist;  --q;  /* [3]-->[4] */
 if (curDist >= (q-1)->theDist) goto storeIt;
 *q = *(q-1);  --q;           /* [2]-->[3] */
 if (curDist >= (q-1)->theDist) goto storeIt;
 *q = *(q-1);  --q;           /* [1]-->[2] */
 if (curDist >= (q-1)->theDist) goto storeIt;
 *q = *(q-1);  --q;           /* [0]-->[1] */
 storeIt:
 q->theDist = curDist;
 q->theIndx = curIndx;
 }
 /*
  *Process next city.
  */
 nextCity:
 curCityP+=sizeof(Str255);
 ++curIndx;
 /*
  *Exit when sentinal is found.
  */
 } while (*(long *)curCityP != kSentinal);

 /*
  *Return indices of 5 closest cities.
  */
 {
 register unsigned short *p = closestMatches;
 register unsigned short *q = &theRec[0].theIndx;

 *p++ = *q;  q+=2;
 *p++ = *q;  q+=2;
 *p++ = *q;  q+=2;
 *p++ = *q;  q+=2;
 *p   = *q;
 }
 return(0);
}

The Rules

Here’s how it works: Each month there will be a different programming challenge presented here. First, you must write some code that solves the challenge. Second, you must optimize your code (a lot). Then, submit your solution to MacTech Magazine (formerly MacTutor). A winner will be chosen based on code correctness, speed, size and elegance (in that order of importance) as well as the postmark of the answer. In the event of multiple equally desirable solutions, one winner will be chosen at random (with honorable mention, but no prize, given to the runners up). The prize for the best solution each month is $50 and a limited edition “The Winner! MacTech Magazine Programming Challenge” T-shirt (not to be found in stores).

In order to make fair comparisons between solutions, all solutions must be in ANSI compatible C (i.e., don’t use Think’s Object extensions). Only pure C code can be used. Any entries with any assembly in them will be disqualified. However, you may call any routine in the Macintosh toolbox you want (i.e., it doesn’t matter if you use NewPtr instead of malloc). All entries will be tested with the FPU and 68020 flags turned off in THINK C. When timing routines, the latest version of THINK C will be used (with ANSI Settings plus “Honor ‘register’ first” and “Use Global Optimizer” turned on) so beware if you optimize for a different C compiler. All code should be limited to 60 characters wide. This will aid us in dealing with e-mail gateways and page layout.

The solution and winners for this month’s Programmers’ Challenge will be published in the issue two months later. All submissions must be received by the 10th day of the month printed on the front of this issue.

All solutions should be marked “Attn: Programmers’ Challenge Solution” and sent to Xplain Corporation (the publishers of MacTech Magazine) via “snail mail” or preferably, e-mail - AppleLink: MT.PROGCHAL, Internet: progchallenge@xplain.com, CompuServe: 71552,174 and America Online: MT PRGCHAL. If you send via snail mail, please include a disk with the solution and all related files (including contact information). See page 2 for information on “How to Contact Xplain Corporation.”

MacTech Magazine reserves the right to publish any solution entered in the Programming Challenge of the Month and all entries are the property of MacTech Magazine upon submission. The submission falls under all the same conventions of an article submission.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Lyn 1.5.11 - Lightweight image browser a...
Lyn is a lightweight and fast image browser and viewer designed for photographers, graphic artists and Web designers. Featuring an extremely versatile and aesthetically pleasing interface, it... Read more
NeoOffice 2014.11 - Mac-tailored, OpenOf...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
LaunchBar 6.4 - 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
Remotix 3.1.4 - Access all your computer...
Remotix is a fast and powerful application to easily access multiple Macs (and PCs) from your own Mac. Features Complete Apple Screen Sharing support - including Mac OS X login, clipboard... Read more
DesktopLyrics 2.6.6 - Displays current i...
DesktopLyrics is an application that displays the lyrics of the song currently playing in "iTunes" right on your desktop. The lyrics for the song have to be set in iTunes; DesktopLyrics does nothing... Read more
VOX 2.5.1 - Music player that supports m...
VOX is a beautiful music player that supports many filetypes. The beauty is in its simplicity, yet behind the minimal exterior lies a powerful music player with a ton of features and support for all... Read more
NetNewsWire 4.0.0 - RSS and Atom news re...
NetNewsWire is the best way to keep up with the sites and authors you read most regularly. Let NetNewsWire pull down the latest articles, and read them in a distraction-free and Mac-like way. Native... Read more
MacUpdate Desktop 6.0.6 - Search and ins...
MacUpdate Desktop 6 brings seamless 1-click installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on macupdate.... Read more
ForkLift 2.6.5 - Powerful file manager:...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more
Drive Genius 4.1.0 - Powerful system uti...
Drive Genius 4 gives you faster performance from your Mac while also protecting it. The award-winning and improved DrivePulse feature alerts you to hard drive issues before they become major problems... Read more

Auroch Digital is Bringing Back Games Wo...
| Read more »
Carbo - Handwriting in the Digital Age...
Carbo - Handwriting in the Digital Age 1.0 Device: iOS Universal Category: Productivity Price: $3.99, Version: 1.0 (iTunes) Description: | Read more »
Draggy Dead (Games)
Draggy Dead 1.1 Device: iOS Universal Category: Games Price: $.99, Version: 1.1 (iTunes) Description: Ditch your dead end job and take up a rewarding career in Grave Robbing today!Guide the recently deceased to a fun filled life of... | Read more »
Bad Dinos (Games)
Bad Dinos 1.0.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.0 (iTunes) Description: | Read more »
The Apple Watch isn't Great as a Fi...
| Read more »
Show the World What You See With Stre.am...
Live broadcasting is getting popular on mobile devices, which is why you can now get Stre.am, by Infinite Takes. [Read more] | Read more »
PhotoTime's 2.1 Update Adds Apple W...
The latest PhotoTime update is adding even more functionality to the handy photo organizing app. Yep, including Apple Watch support. [Read more] | Read more »
Oh My Glob! Adventure Time Puzzle Quest...
Finn and Jake are taking over D3 Go!'s popular puzzle game series in the upcoming Adventure Time Puzzle Quest. [Read more] | Read more »
Earthcore: Shattered Elements - Tips, Tr...
At first glance, Earthcore: Shattered Elements seems like a rather simple card-battling game. Once you’re introduced to skills that will change quite a bit. Even more so once you start to acquire hero cards. But it’s not so complicated that we... | Read more »
Dungeon999F (Games)
Dungeon999F 1.33 Device: iOS Universal Category: Games Price: $.99, Version: 1.33 (iTunes) Description: "The game you must play at least once in your life!" "The game with potential of million downloads globally!" ...is what the... | Read more »

Price Scanner via MacPrices.net

OtterBox Maximizes Portability, Productivity...
From the kitchen recipe book to the boarsroom presentation, the OtterBox Agility Tablet System turns tablets into one of the most versatile pieces of handheld technology available. Available now, the... Read more
Launch of New Car App Gallery and Open Develo...
Automatic, a company on a mission to bring the power of the Internet into every car, has announced the launch of the Automatic App Gallery, an app store for nearly every car or truck on the road... Read more
Memorial Day Weekend Sale: 13-inch 1.6GHz Mac...
Best Buy has the new 13″ 1.6GHz/128GB MacBook Air on sale for $849 on their online store this weekend. Choose free shipping or free local store pickup (if available). Sale price for online orders... Read more
Memorial Day Weekend Sale: 27-inch 3.5GHz 5K...
Best Buy has the 27″ 3.5GHz 5K iMac on sale for $2099.99 this weekend. Choose free shipping or free local store pickup (if available). Sale price for online orders only, in-store prices may vary.... Read more
Sale! 16GB iPad mini 3 for $349, save $50
B&H Photo has the 16GB iPad mini 3 WiFi on sale for $349 including free shipping plus NY sales tax only. Their price is $50 off MSRP, and it’s the lowest price available for this model. Read more
Price drop on 2014 15-inch Retina MacBook Pro...
B&H Photo has dropped prices on 2014 15″ Retina MacBook Pros by $200. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $1799.99 save $200 - 15″ 2.5GHz... Read more
With a Mission to Make Mobile Free, Scratch W...
Scratch Wireless, claiming to be the world’s first truly free mobile service, has announced the availability of a new Scratch-enabled Android smartphone, the Coolpad Arise. The smartphone is equipped... Read more
First-Ever Titanium Alloy Curved iPhone 6 Scr...
One of the most common problems with mobile phones is damage to the screens. The slightest drop can cause a dreaded spider web of gashes and cracks in the glass panel surface that can cost $hundreds... Read more
Preorder new 12-inch MacBook, $10 off, save o...
Adorama has new 12″ Retina MacBooks available for preorder for $10 off MSRP including free shipping plus NY & NJ sales tax only. For a limited time, Adorama will include a free Apple USB-C to USB... Read more
Will iOS 9 Finally Bring Productivity Friendl...
Ah, the irony. From its original announcement in 2010, Apple has doggedly insisted that the iPad remain “simple,” thus arbitrarily limiting its considerable potential as a content creation and... Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
Business Development Manager - *Apple* Pay...
**Job Summary** Apple Pay is seeking an experienced Business Development professional to join the Apple Pay team to develop partnerships and strategic alliances with Read more
Project Manager, *Apple* Retail New Store O...
**Job Summary** An Apple Retail New Store Openings & Remodels Project Manager is responsible for successfully managing the openings, remodels, and small works of Read more
SW QA Engineer - *Apple* TV - Apple (United...
**Job Summary** The Apple TV team is looking for experienced Quality Assurance Engineers with a passion for delivering first in class home entertainment solutions. **Key Read more
Partner Marketing Manager - *Apple* Pay - A...
**Job Summary** The Apple Pay partner marketing team is looking for a marketing manager to develop and drive US marketing programs with our financial institution Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.