Skip to content

Instantly share code, notes, and snippets.

@vladkorotnev
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vladkorotnev/2b0f131d7059e809d119 to your computer and use it in GitHub Desktop.
Save vladkorotnev/2b0f131d7059e809d119 to your computer and use it in GitHub Desktop.
Пьяница — доказательство неразрешимости игры в случае неслучайного и одинакового порядка взятия карт со стола в ротацию
//
// main.m
// Drunk
//
// Created by Akasaka Ryuunosuke on 08/07/15.
// Copyright (c) 2015 Akasaka Ryuunosuke. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NSArray+pull.h"
int main(int argc, const char * argv[]) {
NSArray *cards = @[@6,@7,@8,@9,@10,@1000,@1001,@1002,@1003];
NSArray *trans = @[@"J",@"Q",@"K",@"A"];
@autoreleasepool {
// insert code
if (argc == 1) {
// show help
printf("%s version 1.0\n", argv[0]);
printf("--random - use random deck\n");
printf("--verbose - print all moves\n");
printf("--debug - print decks after all moves and wait for enter to confirm\n");
printf("--reverse - reverse desk when taking cards back into deck\n");
printf("--shuffle-desk - reverse desk when taking cards back into deck\n");
printf("--deck 6/7/8/9/10/J/Q/K/A,... 6/7/8/9/10/J/Q/K/A,... - define custom deck per player\n");
return 1;
}
NSMutableArray * deck1 = [NSMutableArray new];
NSMutableArray * deck2 = [NSMutableArray new];
bool verbose = false, debug=false, shuffle=false, reverse=false;
#define VERBOSE_OUT if(verbose)
#define DEBUG_OUT if(debug)
for (int i = 0; i < argc; i++) {
if ([[NSString stringWithUTF8String:argv[i]]isEqualToString:@"--verbose"]) {
verbose=true;
}
else if ([[NSString stringWithUTF8String:argv[i]]isEqualToString:@"--debug"]) {
verbose=true; debug=true;
}
else if ([[NSString stringWithUTF8String:argv[i]]isEqualToString:@"--shuffle-desk"]) {
shuffle=true;
} else if ([[NSString stringWithUTF8String:argv[i]]isEqualToString:@"--reverse"]) {
reverse=true;
}
}
if (argc >= 2 && [[NSString stringWithUTF8String:argv[1]]isEqualToString:@"--random"]) {
if ([[NSString stringWithUTF8String:argv[1]]isEqualToString:@"--random"]) {
NSMutableArray *c = cards.mutableCopy;
[c addObjectsFromArray:cards];
[c addObjectsFromArray:cards];
[c addObjectsFromArray:cards];
[c shuffle];
for(int i=0; i < c.count; i++ ) {
NSNumber *n = c[i];
if (i % 2 == 0) {
[deck1 addObject:n];
} else {
[deck2 addObject:n];
}
}
} else {
printf("wrong arg %s", argv[1]);
return 1;
}
} else if (argc>= 4 && [[NSString stringWithUTF8String:argv[1]]isEqualToString:@"--deck"]) {
NSArray*deckArg = [[[[[[NSString stringWithUTF8String:argv[2]].uppercaseString
stringByReplacingOccurrencesOfString:@"J"
withString:@"1000"]
stringByReplacingOccurrencesOfString:@"Q"
withString:@"1001"]
stringByReplacingOccurrencesOfString:@"K"
withString:@"1002"]
stringByReplacingOccurrencesOfString:@"A"
withString:@"1003"]
componentsSeparatedByString:@","];
NSArray*deckArg2 = [[[[[[NSString stringWithUTF8String:argv[3]].uppercaseString
stringByReplacingOccurrencesOfString:@"J"
withString:@"1000"]
stringByReplacingOccurrencesOfString:@"Q"
withString:@"1001"]
stringByReplacingOccurrencesOfString:@"K"
withString:@"1002"]
stringByReplacingOccurrencesOfString:@"A"
withString:@"1003"]
componentsSeparatedByString:@","];
if (deckArg.count != 18) {
printf("invalid deck1 length\n");
return 2;
}
if (deckArg2.count != 18) {
printf("invalid deck2 length\n");
return 2;
}
for (NSNumber *n in cards) {
if ([deckArg countItemsEqualTo:[NSString stringWithFormat:@"%i", n.intValue]] + [deckArg2 countItemsEqualTo:[NSString stringWithFormat:@"%i", n.intValue]] > 4) {
printf("too much cards of type: %i", n.intValue);
return 2;
}
}
for (NSString*component in deckArg) {
[deck1 addObject:[NSNumber numberWithInt:component.intValue]];
}
for (NSString*component in deckArg2) {
[deck2 addObject:[NSNumber numberWithInt:component.intValue]];
}
}
// finish filling arrays
printf("Deck 1: ");
for (NSNumber *number in deck1) {
if (number.intValue >= 1000) {
printf("%s ", ((NSString*)trans[number.unsignedIntegerValue-1000]).UTF8String);
} else {
printf("%i ", number.intValue);
}
}
printf("\nDeck 2: ");
for (NSNumber *number in deck2) {
if (number.intValue >= 1000) {
printf("%s ", ((NSString*)trans[number.unsignedIntegerValue-1000]).UTF8String);
} else {
printf("%i ", number.intValue);
}
}
printf("\n\n");
// begin solution
VERBOSE_OUT printf("P1 P2\n");
NSMutableArray * desk = [NSMutableArray new];
unsigned int steps=0;
while (deck1.count > 0 && deck2.count > 0) {
@autoreleasepool {
[desk addObject:[deck1 pull]];
[desk addObject:[deck2 pull]];
VERBOSE_OUT printf("%lu %lu : ",((NSNumber*)desk[desk.count - 2]).unsignedIntegerValue,((NSNumber*)desk[desk.count-1]).unsignedIntegerValue);
while (((NSNumber*)desk[desk.count-1]).unsignedIntegerValue == ((NSNumber*)desk[desk.count - 2]).unsignedIntegerValue) {
VERBOSE_OUT printf("DRAW\n");
if (deck1.count == 0 || deck2.count == 0) {
break;
}
[desk addObject:[deck1 pull]];
[desk addObject:[deck2 pull]];
VERBOSE_OUT printf("%lu %lu : ",((NSNumber*)desk[desk.count - 2]).unsignedIntegerValue,((NSNumber*)desk[desk.count-1]).unsignedIntegerValue);
}
if (((NSNumber*)desk[desk.count-1]).unsignedIntegerValue > ((NSNumber*)desk[desk.count - 2]).unsignedIntegerValue) {
// player 2 won
VERBOSE_OUT printf("P2\n");
if (reverse) {
desk = [desk reverseObjectEnumerator].allObjects.mutableCopy;
}
if (shuffle) {
[desk shuffle];
}
[deck2 addObjectsFromArray:desk];
} else {
VERBOSE_OUT printf("P1\n");
if (reverse) {
desk = [desk reverseObjectEnumerator].allObjects.mutableCopy;
}
if (shuffle) {
[desk shuffle];
}
[deck1 addObjectsFromArray:desk];
}
desk=nil;desk = [NSMutableArray new];
steps++;
DEBUG_OUT {
printf("Deck 1: ");
for (NSNumber *number in deck1) {
if (number.intValue >= 1000) {
printf("%s ", ((NSString*)trans[number.unsignedIntegerValue-1000]).UTF8String);
} else {
printf("%i ", number.intValue);
}
}
printf("\nDeck 2: ");
for (NSNumber *number in deck2) {
if (number.intValue >= 1000) {
printf("%s ", ((NSString*)trans[number.unsignedIntegerValue-1000]).UTF8String);
} else {
printf("%i ", number.intValue);
}
}
getchar();
}
}
}
printf("Game over.\n%s won\nTook %u steps.\n", (deck1.count == 0 ? "P2" : "P1"),steps);
printf("Deck 1: ");
for (NSNumber *number in deck1) {
if (number.intValue >= 1000) {
printf("%s ", ((NSString*)trans[number.unsignedIntegerValue-1000]).UTF8String);
} else {
printf("%i ", number.intValue);
}
}
printf("\nDeck 2: ");
for (NSNumber *number in deck2) {
if (number.intValue >= 1000) {
printf("%s ", ((NSString*)trans[number.unsignedIntegerValue-1000]).UTF8String);
} else {
printf("%i ", number.intValue);
}
}
printf("\n\n");
}
return 0;
}
//
// NSArray+pull.h
// Drunk
//
// Created by Akasaka Ryuunosuke on 08/07/15.
// Copyright (c) 2015 Akasaka Ryuunosuke. All rights reserved.
//
#ifndef Drunk_NSArray_pull_h
#define Drunk_NSArray_pull_h
#import <Foundation/Foundation.h>
@interface NSMutableArray (pull)
- (id) pull;
- (void) shuffle;
@end
@implementation NSMutableArray (pull)
- (id) pull {
id __strong temp = [self objectAtIndex:0];
[self removeObjectAtIndex:0];
return temp;
}
- (void)shuffle
{
NSUInteger count = [self count];
for (NSUInteger i = 0; i < count; ++i) {
NSInteger remainingCount = count - i;
NSInteger exchangeIndex = i + arc4random_uniform((u_int32_t )remainingCount);
[self exchangeObjectAtIndex:i withObjectAtIndex:exchangeIndex];
}
}
@end
@interface NSArray (CountItemsEqualTo)
- (NSUInteger) countItemsEqualTo:(id)equalTo;
@end
@implementation NSArray (CountItemsEqualTo)
- (NSUInteger) countItemsEqualTo:(id)equalTo {
@autoreleasepool {
NSArray * sorted = [self filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject isEqual:equalTo];
}]];
return sorted.count;
}
}
@end
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment