| /* |
| * Copyright 2012 ZXing authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #import "ZXRSSUtils.h" |
| |
| @implementation ZXRSSUtils |
| |
| + (NSArray *)rssWidths:(int)val n:(int)n elements:(int)elements maxWidth:(int)maxWidth noNarrow:(BOOL)noNarrow { |
| NSMutableArray *widths = [NSMutableArray arrayWithCapacity:elements]; |
| int bar; |
| int narrowMask = 0; |
| for (bar = 0; bar < elements - 1; bar++) { |
| narrowMask |= 1 << bar; |
| int elmWidth = 1; |
| int subVal; |
| while (YES) { |
| subVal = [self combins:n - elmWidth - 1 r:elements - bar - 2]; |
| if (noNarrow && (narrowMask == 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) { |
| subVal -= [self combins:n - elmWidth - (elements - bar) r:elements - bar - 2]; |
| } |
| if (elements - bar - 1 > 1) { |
| int lessVal = 0; |
| for (int mxwElement = n - elmWidth - (elements - bar - 2); mxwElement > maxWidth; mxwElement--) { |
| lessVal += [self combins:n - elmWidth - mxwElement - 1 r:elements - bar - 3]; |
| } |
| subVal -= lessVal * (elements - 1 - bar); |
| } else if (n - elmWidth > maxWidth) { |
| subVal--; |
| } |
| val -= subVal; |
| if (val < 0) { |
| break; |
| } |
| elmWidth++; |
| narrowMask &= ~(1 << bar); |
| } |
| val += subVal; |
| n -= elmWidth; |
| [widths addObject:@(elmWidth)]; |
| } |
| |
| [widths addObject:@(n)]; |
| return widths; |
| } |
| |
| + (int)rssValue:(int *)widths widthsLen:(unsigned int)widthsLen maxWidth:(int)maxWidth noNarrow:(BOOL)noNarrow { |
| int elements = widthsLen; |
| int n = 0; |
| for (int i = 0; i < elements; i++) { |
| n += widths[i]; |
| } |
| int val = 0; |
| int narrowMask = 0; |
| for (int bar = 0; bar < elements - 1; bar++) { |
| int elmWidth; |
| for (elmWidth = 1, narrowMask |= 1 << bar; |
| elmWidth < widths[bar]; |
| elmWidth++, narrowMask &= ~(1 << bar)) { |
| int subVal = [self combins:n - elmWidth - 1 r:elements - bar - 2]; |
| if (noNarrow && (narrowMask == 0) && |
| (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) { |
| subVal -= [self combins:n - elmWidth - (elements - bar) |
| r:elements - bar - 2]; |
| } |
| if (elements - bar - 1 > 1) { |
| int lessVal = 0; |
| for (int mxwElement = n - elmWidth - (elements - bar - 2); |
| mxwElement > maxWidth; mxwElement--) { |
| lessVal += [self combins:n - elmWidth - mxwElement - 1 |
| r:elements - bar - 3]; |
| } |
| subVal -= lessVal * (elements - 1 - bar); |
| } else if (n - elmWidth > maxWidth) { |
| subVal--; |
| } |
| val += subVal; |
| } |
| n -= elmWidth; |
| } |
| return val; |
| } |
| |
| + (int)combins:(int)n r:(int)r { |
| int maxDenom; |
| int minDenom; |
| if (n - r > r) { |
| minDenom = r; |
| maxDenom = n - r; |
| } else { |
| minDenom = n - r; |
| maxDenom = r; |
| } |
| int val = 1; |
| int j = 1; |
| for (int i = n; i > maxDenom; i--) { |
| val *= i; |
| if (j <= minDenom) { |
| val /= j; |
| j++; |
| } |
| } |
| while (j <= minDenom) { |
| val /= j; |
| j++; |
| } |
| return val; |
| } |
| |
| + (NSArray *)elements:(NSArray *)eDist N:(int)N K:(int)K { |
| NSMutableArray *widths = [NSMutableArray arrayWithCapacity:[eDist count] + 2]; |
| int twoK = K << 1; |
| [widths addObject:@1]; |
| int i; |
| int minEven = 10; |
| int barSum = 1; |
| for (i = 1; i < twoK - 2; i += 2) { |
| [widths addObject:@([eDist[i - 1] intValue] - [widths[i - 1] intValue])]; |
| [widths addObject:@([eDist[i] intValue] - [widths[i] intValue])]; |
| barSum += [widths[i] intValue] + [widths[i + 1] intValue]; |
| if ([widths[i] intValue] < minEven) { |
| minEven = [widths[i] intValue]; |
| } |
| } |
| |
| [widths addObject:@(N - barSum)]; |
| if ([widths[twoK - 1] intValue] < minEven) { |
| minEven = [widths[twoK - 1] intValue]; |
| } |
| if (minEven > 1) { |
| for (i = 0; i < twoK; i += 2) { |
| widths[i] = @([widths[i] intValue] + minEven - 1); |
| widths[i + 1] = @([widths[i + 1] intValue] - minEven - 1); |
| } |
| } |
| return widths; |
| } |
| |
| @end |