i have a uitableview, which gets populated by a pulling data from a website, so there is a new string for every cell. To that, i want to have show a HEX for the user, based on the text in the cell.
I have tryed myself to make it, without luck, but luckly found a javascript script which does what i try to do. This script, i now need to convert to obj-c, i have tryed it myself, but failed. I hope to get some help.
javascript: http://jsfiddle.net/sUK45/
My try in obj-c (here the strings aint based on the data from the web, but just an array):
unichar hash = 0;
NSArray *strings = [NSArray arrayWithObjects:#"MA", #"Ty", #"Ad", #"ER", nil];
for (int i = 0; i < [[strings objectAtIndex:indexPath.row] length]; i++) {
hash = [[strings objectAtIndex:indexPath.row] characterAtIndex:i] + ((hash < 5) - hash);
}
NSString *colour = #"#";
for (int i = 0; i < 3; i++) {
int value = (hash >> (i * 8)) & 0xFF;
colour = [NSString stringWithFormat:#"%#%d", colour, value];
}
NSLog(#"%#", colour);
But the data i get, aint a useable HEX - NSlog:
#2432550
#3600
#3400
#1200
Probably this is not the only one mistake. Change
hash = [[strings objectAtIndex:indexPath.row] characterAtIndex:i] + ((hash < 5) - hash);
to
hash = [[strings objectAtIndex:indexPath.row] characterAtIndex:i] + ((hash << 5) - hash);
UPDATE:
Also change
colour = [NSString stringWithFormat:#"%#%d", colour, value];
to
colour = [NSString stringWithFormat:#"%#%02x", colour, (unsigned int)value];
UPDATE2:
I have fixed one more error and simplified code:
unsigned int hash = 0;
NSArray *strings = [NSArray arrayWithObjects:#"MA", #"Ty", #"Ad", #"ER", nil];
NSString *string = [strings objectAtIndex:indexPath.row];
for (int i = 0; i < string.length; i++) {
hash = [string characterAtIndex:i] + ((hash << 5) - hash);
}
NSString *color = [NSString stringWithFormat:#"#%06x", hash % 0x1000000];
NSLog(#"%#", color);
Related
In my Objective-C code I'd like to take a NSString value, iterate through the letters, sum ASCII values of the letters and return that to the user (preferably as the NSString too).
I have already written a loop, but I don't know how to get the ASCII value of an individual character. What am I missing?
- (NSString*) getAsciiSum: (NSString*) input {
NSInteger sum = 0;
for (NSInteger index=0; index<input.length; index++) {
sum = sum + (NSInteger)[input characterAtIndex:index];
}
return [NSString stringWithFormat: #"%#", sum];
}
Note: I've seen similar questions related to obtaining ASCII values, but all of them ended up displaying the value as a string. I still don't know how to get ASCII value as NSInteger.
Here is the answer:
- (NSString *) getAsciiSum: (NSString *) input
{
NSString *input = #"hi";
int sum = 0;
for (NSInteger index = 0; index < input.length; index++)
{
char c = [input characterAtIndex:index];
sum = sum + c;
}
return [NSString stringWithFormat: #"%d", sum]);
}
This is working for me.
Hope this helps!
This should work.
- (NSInteger)getAsciiSum:(NSString *)stringToSum {
int asciiSum = 0;
for (int i = 0; i < stringToSum.length; i++) {
NSString *character = [stringToSum substringWithRange:NSMakeRange(i, 1)];
int asciiValue = [character characterAtIndex:0];
asciiSum = asciiSum + asciiValue;
}
return asciiSum;
}
Thank you to How to convert a NSString to NSInteger with the sum of ASCII values? for the reference.
Not sure exactly how to word this but basically I am doing this:
unsigned int propCount = 0;
objc_property_t *properties = class_copyPropertyList([self class], &propCount);
for(int idx = 0; idx < propCount; idx++) {
objc_property_t prop = *(properties + idx);
NSString *key = #(property_getName(prop));
NSString *key2 = #(property_getAttributes(prop));
NSLog(#"%#::%#", key,key2);
}
and it prints out
describeOther::T#"UITextField",&,N,V_describeOther
how can I assign "UITextField" to something or is it already assigned and I can access it like key2[1] or something??
EDIT:
I guess I could do a if statement with a contains constraint but not sure if thats the "cleanest" way to do it.
Get the range of the two double-quotes and extract the substring between those two ranges.
NSRange openQuote = [key2 rangeOfString:#"\""];
NSRange closeQuote = [key2 rangeOfString#"\"" options:NSBackwardsSearch];
NSUInteger start = openQuote.location + openQuote.length;
NSUInteger end = closeQuote.location;
NSRange nameRange = NSRangeMake(start, end - start);
NSString *name = [keys substringWithRange:nameRange);
I am having trouble with some code. I narrowed it down to this problem: first of all, reverseString and 2 are both NSMutableStrings _input1 and _input2 are NSStrings, i'm trying to add zeros to the smallest string but it's not working correctly, this is what I got. reverseString is #"123" and reverseString2 is #"34567".
//they get initialized back into the original strings
_input1=reversedString;
_input2=reversedString2;
//appends 0 to the shortest value
while ([_input1 length]>[_input2 length]){
_input2=[_input2 stringByAppendingString:#"0"];
_length=[_input1 length];
}
while ([_input1 length]<[_input2 length]){
_input1=[_input1 stringByAppendingString:#"0"];
_length=[_input2 length];
}
//converts the string to an NSArray
for (int i=0; i <([_input1 length]); i++) {
NSString *TempStr = [_input1 substringWithRange:NSMakeRange(i, 1)];
[one addObject:[TempStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
for (int i=0; i <([_input2 length]); i++) {
NSString *TempStr2 = [_input2 substringWithRange:NSMakeRange(i, 1)];
[two addObject:[TempStr2 stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
Now I noticed that when it goes through this loop, the smallest one, _input1, gets set to #"" instead of adding zeros to the end. This is within a class, by the way.
This is also an error I receive:
objc[2291]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[2291]: receiver 0x100300830, SEL 0x7fff8a689779, isa 0x7fff727b8bd0, cache 0x7fff727b8be0, buckets 0x7fff89b9b09c, mask 0x1, occupied 0x0, wrap bucket 0x7fff89b9b09c
objc[2291]: receiver 0 bytes, buckets 0 bytes
objc[2291]: selector 'length'
(lldb)
Just try with following code
if([_input1 length] > [_input2 length])
{
for (int i = 0 ; i < [_input1 length] - [_input2 length] ; i ++)
_input2 = [_input2 stringByAppendingString:#"0"];
}
else
{
for (int i = 0 ; i < [_input2 length] - [_input1 length] ; i ++)
_input1 = [_input1 stringByAppendingString:#"0"];
}
Try like this:-
NSString *input1=#"123";
NSString * input2=#"34567";
NSMutableArray *one=[NSMutableArray array];
NSMutableArray *two=[NSMutableArray array];
//appends 0 to the shortest value
while ([input1 length]>[input2 length]){
input2=[input2 stringByAppendingString:#"0"];
//length=[input1 length];
}
while ([input1 length]<[input2 length]){
input1=[input1 stringByAppendingString:#"0"];
// length=[input2 length];
}
for (int i=0; i <([input1 length]); i++) {
NSString *TempStr = [input1 substringWithRange:NSMakeRange(i, 1)];
[one addObject:[TempStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(#"%ld",[one count]);
for (int i=0; i <([input2 length]); i++) {
NSString *TempStr2 = [input2 substringWithRange:NSMakeRange(i, 1)];
[two addObject:[TempStr2 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(#"%ld",[two count]);
Well your requirements are not very clear, but here's a cleaner version of the code you proposed
NSString *string1 = #"foo";
NSString *string2 = #"foobar";
// Compute the desired length
NSUInteger length = MAX(string1.length, string2.length);
// We will pad using this string
NSString *paddingString = #"0";
// Pad both strings to the same length
string1 = [string1 stringByPaddingToLength:length withString:paddingString startingAtIndex:0];
string2 = [string2 stringByPaddingToLength:length withString:paddingString startingAtIndex:0];
// Build two arrays containing the characters, percent escaped
NSMutableArray *charactersArray1 = [NSMutableArray arrayWithCapacity:string1.length];
NSMutableArray *charactersArray2 = [NSMutableArray arrayWithCapacity:string2.length];
for (NSInteger i = 0; i < string1.length; i++) {
[charactersArray1 addObject:[[string1 substringWithRange:(NSRange){ i, 1 }] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[charactersArray2 addObject:[[string2 substringWithRange:(NSRange){ i, 1 }] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(#"String 1: %#\nString 2: %#", charactersArray1, charactersArray2);
The result will be
String 1: [ f, o, o, 0, 0, 0 ]
String 2: [ f, o, o, b, a, r ]
I figured out my problem, _input1 and _input2 were bad pointers and i had to fix it, sorry for all the confusion, in the end i got my code to work!
I want a string of all the characters of the alphabet randomized. Right now, I create a mutable array of the 26 characters, shuffle them with the exchangeObjectAtIndex: method and then add each character to a string that I return.
There has to be a better way to do this. Here is my code:
- (NSString *)shuffledAlphabet {
NSMutableArray * shuffledAlphabet = [NSMutableArray arrayWithArray:#[#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z"]];
for (NSUInteger i = 0; i < [shuffledAlphabet count]; ++i) {
// Select a random element between i and end of array to swap with.
int nElements = [shuffledAlphabet count] - i;
int n = (random() % nElements) + i;
[shuffledAlphabet exchangeObjectAtIndex:i withObjectAtIndex:n];
}
NSString *string = [[NSString alloc] init];
for (NSString *letter in shuffledAlphabet) {
string = [NSString stringWithFormat:#"%#%#",string,letter];
}
return string;
}
Here's an efficient Fisher-Yates shuffle, adapted to your use case:
- (NSString *)shuffledAlphabet {
NSString *alphabet = #"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Get the characters into a C array for efficient shuffling
NSUInteger numberOfCharacters = [alphabet length];
unichar *characters = calloc(numberOfCharacters, sizeof(unichar));
[alphabet getCharacters:characters range:NSMakeRange(0, numberOfCharacters)];
// Perform a Fisher-Yates shuffle
for (NSUInteger i = 0; i < numberOfCharacters; ++i) {
NSUInteger j = (arc4random_uniform(numberOfCharacters - i) + i);
unichar c = characters[i];
characters[i] = characters[j];
characters[j] = c;
}
// Turn the result back into a string
NSString *result = [NSString stringWithCharacters:characters length:numberOfCharacters];
free(characters);
return result;
}
This is the more efficient way to perform a correctly shuffled alphabet generation.
- (NSString *)shuffledAlphabet
{
const NSUInteger length = 'Z' - 'A' + 1;
unichar alphabet[length];
alphabet[0] = 'A';
for ( NSUInteger i = 1; i < length; i++ )
{
NSUInteger j = arc4random_uniform((uint32_t)i + 1);
alphabet[i] = alphabet[j];
alphabet[j] = 'A' + i;
}
return [NSString stringWithCharacters:alphabet length:length];
}
It uses the "inside-out" version of the Fischer Yates shuffle and avoids modula bias by generating the pseudorandom numbers with arc4random_uniform. Also, it requires a single allocation as all the permutations are performed in a temporary buffer.
Generating random numbers in Objective-C does this help?
*generate random number
*divide by 26 and take reminder
*index array[reminder]
You could pick random elements from the (remaining) alphabet while you build your string instead of shuffling it first:
NSMutableArray *alphabet = [NSMutableArray arrayWithObjects:#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z", nil];
NSMutableString *result = [NSMutableString string];
NSUInteger numberOfLetters = alphabet.count;
for (NSUInteger i = 0; i < numberOfLetters; i++) {
int n = arc4random() % alphabet.count;
[result appendString:[alphabet objectAtIndex:n]];
[alphabet removeObjectAtIndex:n];
}
NSLog(#"%#", result);
This makes the code a bit shorter. Note also that using NSMutableString is more efficient than creating a new NSString each time a letter is added.
I'm trying this code...
NSString *tileString = [[NSString alloc] init];
for (int i = 0; i < [[GameP objectForKey:#"groundMap"] length]; i += 5) {
tileString = [[GameP objectForKey:#"groundMap"] substringWithRange:NSMakeRange(i, 5)];
[tileString stringByAppendingString:#"0000"];
[sharedInstance.groundMap addObject:tileString];
}
The 5 char string that's coming from the object is "t0001", so I want to end up with "t0001000" but it's not working, when I check sharedInstance.groundMap all the strings in the array are still "t0001"
Should I be using NSMutableString instead?
You aren't assigning the result. Change this:
[tileString stringByAppendingString:#"0000"];
to:
titleString = [tileString stringByAppendingString:#"0000"];
There's a little more cleanup you can do too:
for (int i = 0; i < [[GameP objectForKey:#"groundMap"] length]; i += 5) {
NSString *tileString = [[GameP objectForKey:#"groundMap"] substringWithRange:NSMakeRange(i, 5)];
titleString = [tileString stringByAppendingString:#"0000"];
[sharedInstance.groundMap addObject:tileString];
}