# C++ timer



## joey (Dec 9, 2011)

I was bored, so I started working on a C++ timer, using Qt as the GUI.

https://bitbucket.org/captainjey/cpptimer

If anyone is interested on doing some work on it, go ahead


----------



## IngeneroiOS (Dec 13, 2011)

If you'd like a better scrambler, I can provide my Objective-C port of the WCA scrambler (prevents redundant moves, supports different cube sizes). It would take some adapting to port to C++, but would be easier than porting the Javascript.


----------



## joey (Dec 13, 2011)

Sure I'd be willing to take a look. I already have a Java version (from jjtimer), but an Obj-C one would be interesting.


----------



## IngeneroiOS (Dec 14, 2011)

Here it is. It's a messy port, but it works and it works quickly. I removed the cubeOrient functionality as I had no need for it.


```
@interface Scrambler : NSObject {
    NSMutableArray *seq;
  //  var flat2posit;	//lookup table for drawing cube
}

@property (nonatomic) int size;
@property (nonatomic) int seqlen;

-(void)generateSequenceOfScrambles;
-(NSString *) generateScrambleString;
-(id) initWithSize:(int)sizeToSet andLength:(int)lengthToSet;

@end
```


```
@implementation Scrambler
@synthesize size, seqlen;

int size = 3;
int seqlen = 25; 
int numcub = 1;
bool mult=false;
bool cubeorient=false;

//int seq[1][1];

-(id) initWithSize:(int)sizeToSet andLength:(int)lengthToSet {
    self = [super init];
    if(self) {
        size = sizeToSet;
        seqlen = lengthToSet; 
        [self generateSequenceOfScrambles];
    }
    return self;
}

// append set of moves along an axis to current sequence in order
-(NSMutableArray*) appendMoveSequence:(NSMutableArray*)sq WithAxsl:(NSMutableArray*)axsl andTl:(int)tl andLa:(int)la {
	for( int sl = 0; sl < tl; sl++){	// for each move type
		if([[axsl safeObjectAtIndex:sl] intValue] != 0 /* axsl[sl]*/){				// if it occurs
			int q = ([[axsl safeObjectAtIndex:sl] intValue]-1); //This ought not be negative
            
			// get semi-axis of this move
			int sa = la;
			int m = sl;
			if(sl+sl+1>=tl){ // if on rear half of this axis
				sa+=3; // get semi-axis (i.e. face of the move)
				m=tl-1-m; // slice number counting from that face
				q=2-q; // opposite direction when looking at that face
			}

			// store move
            int sqIndex = [sq count];
            //Returning negatives = bad!
			[sq insertObject:[NSNumber numberWithInt:((m*6+sa)*4+q)] atIndex:sqIndex];
        }
        
	}
    return sq;
}

// generate sequence of scambles
-(void)generateSequenceOfScrambles{
	//tl=number of allowed moves (twistable layers) on axis -- middle layer ignored
	int tl = size;
    if (!seq) {
        seq = [NSMutableArray array];
    }
	if(mult || (size&1)!=0 ) tl--;
	//set up bookkeeping
    int axsl[tl];
    int axam[] = {0,0,0};
	int la; // last axis moved
    
	// for each cube scramble
	for(int  n=0; n < numcub; n++){
		// initialise this scramble
		la = -1;
		// reset slice/direction counters
		for( int i=0; i<tl; i++) {
            axsl[i] = 0;
        }
		axam[0] = axam[1] = axam[2] = 0;
		int moved = 0;
        
		// while generated sequence not long enough
		while([seq count] + moved <= seqlen /*sequence length*/ ){
            //Dlog(@"[seq count] = %i", [seq count]);
			int ax, sl, q;
			do{
				do{
					// choose a random axis
                    ax = arc4random() % 3;
                    
					// choose a random move type on that axis
					sl= arc4random() % tl;
					// choose random amount
					q= arc4random() % 3;
                    
				}while( ax==la && axsl[(int)sl] !=0 );		// loop until have found an unused movetype
			}while( ax==la					// loop while move is reducible: reductions only if on same axis as previous moves
                   && !mult				// multislice moves have no reductions so always ok
                   && tl==size				// only even-sized cubes have reductions (odds have middle layer as reference)
                   && (
                       2*axam[0]==tl ||	// reduction if already have half the slices move in same direction
                       2*axam[1]==tl ||
                       2*axam[2]==tl ||
                       (
                        2*(axam[(int)q]+1)==tl	// reduction if move makes exactly half the slices moved in same direction and
                        &&
                        axam[0]+axam[1]+axam[2]-axam[(int)q] > 0 // some other slice also moved
						)
                       )
                   );
            
			// if now on different axis, dump cached moves from old axis
			if( ax!=la ) {
                NSMutableArray *axslObject = [NSMutableArray array];
                
                for (int i = 0; i < sizeof(axsl)/sizeof(int); i++) {
                    NSNumber *num = [[NSNumber alloc] initWithInt:axsl[i]];
                    [axslObject addObject:num];
                    [num release];
                }
                seq = [self appendMoveSequence:seq WithAxsl:axslObject andTl:tl andLa:la];
				// reset slice/direction counters
				for( int i=0; i<tl; i++)  axsl[i]=0;
				axam[0]=axam[1]=axam[2]=0;
				moved = 0;
				// remember new axis
				la=ax;
			}
            
			// adjust counters for this move
			axam[q] = axam[q] + 1;// adjust direction count
			moved++;
			axsl[(int)sl]=q+1;// mark the slice has moved amount
            
		}
        NSMutableArray *axslObject = [NSMutableArray array];
        
        for (int i = 0; i < sizeof(axsl)/sizeof(int); i++) { //Convert C int[] into NSArray
            NSNumber *n = [[NSNumber alloc] initWithInt:axsl[i]];
            [axslObject addObject:n];
            [n release];
        }
		// dump the last few moves
        seq = [self appendMoveSequence:seq WithAxsl:axslObject andTl:tl andLa:la];
    }
    
}

-(NSString *) generateScrambleString {
	NSMutableString *s= [NSMutableString string];
    int j;
	for(int i=0; i<([seq count] - 1); i++){
		if( i!=0 ) [s appendString:@" "];
		int k = [[seq  safeObjectAtIndex:i] intValue] >>2;
        
		j = k%6;
        k=(k-j)/6;
		if( k && size<=5 && !mult ) {
            const unichar wantedChar = [@"dlburf" characterAtIndex:j];
            [s appendString:[NSString stringWithCharacters:&wantedChar length:1]];
		//	s+="dlburf".charAt(j);	// use lower case only for inner slices on 4x4x4 or 5x5x5
		}else{
			if(size<=5 && mult ){
                const unichar wantedChar = [@"DLBURF" characterAtIndex:j];
                [s appendString:[NSString stringWithCharacters:&wantedChar length:1]];
			//	s+="DLBURF".charAt(j);
				if(k>0) [s appendString:@"w"];	// use w only for double layers on 4x4x4 and 5x5x5
			}
			else{
				if(k>0) [s appendFormat:@"%i", (k+1)];
                const unichar wantedChar = [@"DLBURF" characterAtIndex:j];
                [s appendString:[NSString stringWithCharacters:&wantedChar length:1]];
				//s+="DLBURF".charAt(j);
			}
		}
        j = [[seq safeObjectAtIndex:i] intValue]&3;
		//j=seq[n][i]&3;
        if(j!=0) {
            const unichar wantedChar = [@" 2'" characterAtIndex:j];
          [s appendString:[NSString stringWithCharacters:&wantedChar length:1]];  
        }
                //s+=" 2'".charAt(j);
	}
	return s;
}

@end
```

If you have any questions about the Obj-C, I can explain what it does (not sure of your familiarity). It's mostly C, though. -[NSArray safeObjectAtIndex:] is simply a version of -[NSArray objectAtIndex:] which ensures there isn't a range exception (e.g. index < [self count]).


----------

