简体   繁体   中英

Translate recursive JS function into Obj-C

A friend of mine helped me work through a computation problem where I am trying to create a series based on some conditions. He used JS with recursion. I sat down to translate this into Obj-C and am stumped.

I have the starting point below. The idea was to use a recursive block, is that the right approach? Blocks and recursion are really hard for me to get my head around. Is the skeleton below on the right track?

JS Version

function series(F, S, Y, N = 0, result = []) {
  var entry

  if (N < 2) {
    entry = N * (F + S * (N - 1))
  } else {
    entry = (F + S * (N - 1))
  }

  if (entry > Y) {
    return result
  }

  result.push(entry)

  return series(F, S, Y, N + 1, result)
}

// series (90, 30, 200)
// (5) [0, 90, 120, 150, 180]

Starting of Attempt at Obj-C Version -- sorry this is ugly

-(NSArray*) seriesWithF:(int)_F S:(int)_S Y:(int)_Y {

int F = _F;
int S = _S;
int Y = _Y;
int N = 0;
NSMutableArray* result = [NSMutableArray init];

    __block void ( ^series)(int, int, int, int, NSMutableArray*) = ^ void (int F, int S, int Y, int N, NSMutableArray* result) 
    {

    // logic
    int entry = [result of logic]
    [result addObject:[NSNumber initWithInt:entry]];

     series(F, S, Y, N, result);

    }

 series(F, S, Y, N, result);
 return result;

}     

There is no need for the block. A much more direct translation works:

- (NSArray *)series:(int)f s:(int)s y:(int)y n:(int)n result:(NSArray *)result {
    int entry;
    if (n < 2) {
        entry = n * (f + s * (n - 1));
    } else {
        entry = (f + s * (n - 1));
    }

    if (entry > y) {
        return result;
    }

    NSMutableArray *newResult = [result mutableCopy];
    [newResult addObject:@(entry)];

    return [self series:f s:s y:y n:n+1 result:newResult];
}

- (void)someOtherMethod {
    NSArray *result = [self series:90 s:30 y:200 n:0 result:@[]];
    NSLog(@"Result = %@", result);
}

It looks like you have used a block to address the lack of default parameter values (for N and result ), there is nothing wrong with your code outline per se but a simpler approach is to use a local ( static ) C function to do the job. To do this simply translate the JS into the equivalent C and then use your Objective-C method to call this C function passing in the values for N and result .

However in this particular case your friends solution is more complicated than it need be, a much simpler algorithm will produce your series.

Consider the first condition, N < 2 , which given N starts at zero will be true for just 0 & 1 . In the first case entry will be set to 0 and in the second to the same value as it would be in the else branch... A complex way to set the first value in your sequence to zero.

Next consider the recursion; there is nothing complex involved in the call, just one parameter is incremented. Incrementing a value is easily done with iteration.

Finally each recursive call calculates the next value "from scratch", but that next value is just the previous one with S added to it. Again iteration is suited to this.

Based on these observations let's simplify:

- (NSArray *) seriesWithF:(int)F S:(int)S Y:(int)Y
{
   NSMutableArray *result = [NSMutableArray new];
   [result addObject:@(0)];        // you always start with zero

   int entry = F;                  // next value is F
   while (entry <= Y)              // iterate as long as in range
   {
      [result addObject:@(entry)]; // add to sequence
      entry += S;                  // increment
   }

   return result;
}

HTH

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM