Wednesday, June 18, 2014

uiimage to nsdata to nsstring to nsdata to uiimage

Why would you want to make these conversions?

nsstring is a format that can be sent to any system.  In my case I want to send it to an SQLite database.  However, SQLite does not support images.  the closest thing to it is a blob type.  A blog type accepts a bunch of bytes.  While this is good, it might not always suit your purposes.

If you do not want to use a blob type, you can use the text type.  In the following blog post I will detail how to convert an uiimage to nsdata to nsstring.  Then how to turn that nsstring back to data then back to uiimage.


UIImage *originalImage = ...; //get image from somewhere.  a path or an iphoto library.

NSData *originalData = UIImagePNGRepresentation(originalImage);

NSString *originalString = [originalData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

//Now that you have the data in a string format you can pass it around.  In my case I stored it in my SQLite database.  Now if I want to retrieve it I need to convert it back.

NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:originalString options:NSDataBase64DecodingIgnoreUnknownCharacters];

UIImage *decodedImage = [UIImage imageWithData:decodedData];

-------------------
There is only one decoder option: "NSDataBase64DecodingIgnoreUnknownCharacters"
But there are four encoder options.  In the example above I used "NSDataBase64Encoding64CharacterLineLength"

but there are 3 others.  What are the differences and why would you use them?


  • NSDataBase64Encoding64CharacterLineLength
    • Sets the maximum line length to 64 characters, after which a line ending is inserted.
  • NSDataBase64Encoding76CharacterLineLength
    • Sets the maximum line Length to 76 characters, after which a line ending is inserted.
  • NSDataBase64EncodingEndLineWithCarriageReturn
    • When a maximum line length is set, specify that the line ending to insert should include a carriage return
  • NSDataBase64EncodingEndLineWithLineFeed
    • When a maximum line length is set, specify that the line ending to insert should include a line feed.

Wednesday, June 11, 2014

Xvolve programming assignment

You are given two lines.
the first line tells you how many numbers (N) are in the array, the second tells you the difference(K) that you must find.
The second line give you a string of numbers.
Your goal is to count the number of numbers that have a difference (K).

input
5 2
1 5 3 4 2

output
3

in the above input N is 5 and K is 2.  I must find all numbers that have a difference of 2.
There are two ways to do this.  The brute fore way and the better way.  The brute force way does it the way that you would expect.  Create an array of numbers and for each number compare it to every other number until you get to the end.  then you increment to the next number lined up and compare that to every other number until you reach the end.  The running time of this algorithm is O(n^2).  It gets the job done but it does too many comparisons.

the brute force method is called match1.
The better method is called match2.

First it sorts the array of numbers.  We start at the left most index i and compare it to index j.  We will compare it until the values of j are greater than the expected diff.  If it is less than K we increment j to the next.  if it is the same as K then we increment numberOfMatches and then increment J.

This actuall results in much less comparisons.

look at my test cases:
(10)
3
(9)
3
(31996000)
0
(7999)
0
$
(7998000)
0
(3999)
0
(45)
0

(9)
0

After the dollar sign we the I show the number of comparisons, the number of matchs for brute force, the next two are the better method.  Observe the difference.

I think the better method is O(nlogn)

Code is below

#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) {
return *(int*)a - *(int*)b;
}

int match1(int *arrOfNum, int len, int diff) {
int i,j;
int numMatches=0;
int numComparisons = 0;
    for(i = 0; i < len-1; ++i) {
    for(j = i + 1; j < len; ++j) {
    //printf("%d - %d\n", arrOfNum[i], arrOfNum[j]);
    numComparisons++;
    if(abs(arrOfNum[i] - arrOfNum[j]) == diff) {
    numMatches++;
    }
    }
    }
    printf("(%d)\n", numComparisons);
    return numMatches;
}

int match2(int *arrOfNum, int len, int diff) {
qsort(arrOfNum, len, sizeof(int), compare);
    int i = 0, j = i + 1;
    int *a = arrOfNum;
    int numMatches = 0;
    int numComparisons = 0;
    for(; i < len-1;++i) {
    for(j = i + 1; j < len;++j) {
    //printf("%d - %d\n", arrOfNum[i], arrOfNum[j]);
    numComparisons++;
    if(a[i] + diff > a[j]) {continue;}
    else if(a[i] + diff == a[j]){
    numMatches++;
    } else {
    break;
    }
    }
    }
    printf("(%d)\n", numComparisons);
    return numMatches;
}



int main(int argc, char **argv) {
    char cN[10];
    char cK[10];
    char number[20];
    FILE *f = fopen(argv[1], "r");
    if (!f){ //error
        return -1;
    }
    fscanf(f, "%s %s", cN, cK);
    int N = (int)strtol(cN, NULL, 10);
    int K = (int)strtol(cK, NULL, 10);

    int numMatches = 0;
    int arrOfNum[100000];
    int i = 0;
    while(1 == fscanf(f, "%s", number)) {
    arrOfNum[i] = (int)strtol(number, NULL, 10);
    ++i;
    }


    numMatches = match1(arrOfNum, N, K);
    printf("%d\n", numMatches);
     numMatches = match2(arrOfNum, N, K);

    printf("%d\n", numMatches);
    return 0;
}