Testcase failed after converting codes from Objective-C to Swift - ios

I am doing some bitwise operations in Swift style, which these codes are originally written in Objective-C/C. I use UnsafeMutablePointer to state the beginning index of memory address and use UnsafeMutableBufferPointer for accessing the element within the scope.
You can access the original Objective-C file Here.
public init(size: Int) {
self.size = size
self.bitsLength = (size + 31) / 32
self.startIdx = UnsafeMutablePointer<Int32>.alloc(bitsLength * sizeof(Int32))
self.bits = UnsafeMutableBufferPointer(start: startIdx, count: bitsLength)
}
/**
* #param from first bit to check
* #return index of first bit that is set, starting from the given index, or size if none are set
* at or beyond its given index
*/
public func nextSet(from: Int) -> Int {
if from >= size { return size }
var bitsOffset = from / 32
var currentBits: Int32 = bits[bitsOffset]
currentBits &= ~((1 << (from & 0x1F)) - 1).to32
while currentBits == 0 {
if ++bitsOffset == bitsLength {
return size
}
currentBits = bits[bitsOffset]
}
let result: Int = bitsOffset * 32 + numberOfTrailingZeros(currentBits).toInt
return result > size ? size : result
}
func numberOfTrailingZeros(i: Int32) -> Int {
var i = i
guard i != 0 else { return 32 }
var n = 31
var y: Int32
y = i << 16
if y != 0 { n = n - 16; i = y }
y = i << 8
if y != 0 { n = n - 8; i = y }
y = i << 4
if y != 0 { n = n - 4; i = y }
y = i << 2
if y != 0 { n = n - 2; i = y }
return n - Int((UInt((i << 1)) >> 31))
}
Testcase:
func testGetNextSet1() {
// Passed
var bits = BitArray(size: 32)
for i in 0..<bits.size {
XCTAssertEqual(32, bits.nextSet(i), "\(i)")
}
// Failed
bits = BitArray(size: 34)
for i in 0..<bits.size {
XCTAssertEqual(34, bits.nextSet(i), "\(i)")
}
}
Can someone guide me why the second testcase fail but the objective-c version pass ?
Edit: As #vacawama mentioned: If you break testGetNextSet into 2 tests, both pass.
Edit2: When I run tests with xctool, and tests which calling BitArray's nextSet() will crash while running.

Objective-C version of numberOfTrailingZeros:
// Ported from OpenJDK Integer.numberOfTrailingZeros implementation
- (int32_t)numberOfTrailingZeros:(int32_t)i {
int32_t y;
if (i == 0) return 32;
int32_t n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - (int32_t)((uint32_t)(i << 1) >> 31);
}
When translating numberOfTrailingZeros, you changed the return value from Int32 to Int. That is fine, but the last line of the function is not operating properly as you translated it.
In numberOfTrailingZeros, replace this:
return n - Int((UInt((i << 1)) >> 31))
With this:
return n - Int(UInt32(bitPattern: i << 1) >> 31)
The cast to UInt32 removes all but the lower 32 bits. Since you were casting to UInt, you weren't removing those bits. It is necessary to use bitPattern to make this happen.

Finally I found out that startIdx just need to be initialized after allocation.
self.startIdx = UnsafeMutablePointer<Int32>.alloc(bitsLength * sizeof(Int32))
self.startIdx.initializeFrom(Array(count: bitsLength, repeatedValue: 0))
Or use calloc with just one line code:
self.startIdx = unsafeBitCast(calloc(bitsLength, sizeof(Int32)), UnsafeMutablePointer<Int32>.self)
Furthermore, I use lazy var to defer the Initialization of UnsafeMutableBufferPointer until the property is first used.
lazy var bits: UnsafeMutableBufferPointer<Int32> = {
return UnsafeMutableBufferPointer<Int32>(start: self.startIdx, count: self.bitsLength)
}()
On the other hand, don't forget to deinit:
deinit {
startIdx.destroy()
startIdx.dealloc(bitsLength * sizeof(Int32))
}

Related

How to generate very sharp color scale for below zero and above zero?

I'm encountering a big problem when using the number 0 (zero) as a factor for the colors to generate scales, the numbers close to 0 (zero) end up becoming almost white, impossible to see a difference.
The idea is that above 0 (zero) it starts green and gets even stronger and below 0 (zero) starting with a red one and getting stronger.
I really need any number, even if it's 0.000001 already has a visible green and the -0.000001 has a visible red.
Link to SpreadSheet:
https://docs.google.com/spreadsheets/d/1uN5rDEeR10m3EFw29vM_nVXGMqhLcNilYrFOQfcC97s/edit?usp=sharing
Note to help with image translation and visualization:
Número = Number
Nenhum = None
Valor Máx. = Max Value
Valor Min. = Min Value
Current Result / Expected Result
After reading your new comments I understand that these are the requisites:
The values above zero should be green (with increased intensity the further beyond zero).
The values below zero should be red (with increased intensity the further beyond zero).
Values near zero should be coloured (not almost white).
Given those requisites, I developed an Apps Script project that would be useful in your scenario. This is the full project:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Extra").addItem("Generate gradient", "parseData").addToUi();
}
function parseData() {
var darkestGreen = "#009000";
var lighestGreen = "#B8F4B8";
var darkestRed = "#893F45";
var lighestRed = "#FEBFC4";
var range = SpreadsheetApp.getActiveRange();
var data = range.getValues();
var biggestPositive = Math.max.apply(null, data);
var biggestNegative = Math.min.apply(null, data);
var greenPalette = colourPalette(darkestGreen, lighestGreen, biggestPositive);
var redPalette = colourPalette(darkestRed, lighestRed, Math.abs(
biggestNegative) + 1);
var fullPalette = [];
for (var i = 0; i < data.length; i++) {
if (data[i] > 0) {
var cellColour = [];
cellColour[0] = greenPalette[data[i] - 1];
fullPalette.push(cellColour);
} else if (data[i] < 0) {
var cellColour = [];
cellColour[0] = redPalette[Math.abs(data[i]) - 1];
fullPalette.push(cellColour);
} else if (data[i] == 0) {
var cellColour = [];
cellColour[0] = null;
fullPalette.push(cellColour);
}
}
range.setBackgrounds(fullPalette);
}
function colourPalette(darkestColour, lightestColour, colourSteps) {
var firstColour = hexToRGB(darkestColour);
var lastColour = hexToRGB(lightestColour);
var blending = 0.0;
var gradientColours = [];
for (i = 0; i < colourSteps; i++) {
var colour = [];
blending += (1.0 / colourSteps);
colour[0] = firstColour[0] * blending + (1 - blending) * lastColour[0];
colour[1] = firstColour[1] * blending + (1 - blending) * lastColour[1];
colour[2] = firstColour[2] * blending + (1 - blending) * lastColour[2];
gradientColours.push(rgbToHex(colour));
}
return gradientColours;
}
function hexToRGB(hex) {
var colour = [];
colour[0] = parseInt((removeNumeralSymbol(hex)).substring(0, 2), 16);
colour[1] = parseInt((removeNumeralSymbol(hex)).substring(2, 4), 16);
colour[2] = parseInt((removeNumeralSymbol(hex)).substring(4, 6), 16);
return colour;
}
function removeNumeralSymbol(hex) {
return (hex.charAt(0) == '#') ? hex.substring(1, 7) : hex
}
function rgbToHex(rgb) {
return "#" + hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
function hex(c) {
var pool = "0123456789abcdef";
var integer = parseInt(c);
if (integer == 0 || isNaN(c)) {
return "00";
}
integer = Math.round(Math.min(Math.max(0, integer), 255));
return pool.charAt((integer - integer % 16) / 16) + pool.charAt(integer % 16);
}
First of all the script will use the Ui class to show a customised menu called Extra. That menu calls the main function parseData, that reads the whole selection data with getValues. That function holds the darkest/lightest green/red colours. I used some colours for my example, but I advise you to edit them as you wish. Based on those colours, the function colourPalette will use graphical linear interpolation between the two colours (lightest and darkest). That interpolation will return an array with colours from darkest to lightest, with as many in-betweens as the maximum integer in the column. Please notice how the function uses many minimal functions to run repetitive tasks (converting from hexadecimal to RGB, formatting, etc…). When the palette is ready, the main function will create an array with all the used colours (meaning that it will skip unused colours, to give sharp contrast between big and small numbers). Finally, it will apply the palette using the setBackgrounds method. Here you can see some sample results:
In that picture you can see one set of colours per column. Varying between random small and big numbers, numerical series and mixed small/big numbers. Please feel free to ask any doubt about this approach.
A very small improvement to acques-Guzel Heron
I made it skip all non numeric values, beforehand it just errored out.
I added an option in the menu to use a custom range.
Thank you very much acques-Guzel Heron
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Extra')
.addItem('Generate gradient', 'parseData')
.addItem('Custom Range', 'customRange')
.addToUi();
}
function parseData(customRange = null) {
const darkestGreen = '#009000';
const lighestGreen = '#B8F4B8';
const darkestRed = '#893F45';
const lighestRed = '#FEBFC4';
let range = SpreadsheetApp.getActiveRange();
if (customRange) {
range = SpreadsheetApp.getActiveSpreadsheet().getRange(customRange);
}
const data = range.getValues();
const biggestPositive = Math.max.apply(null, data.filter(a => !isNaN([a])));
const biggestNegative = Math.min.apply(null, data.filter(a => !isNaN([a])));
const greenPalette = colorPalette(darkestGreen, lighestGreen, biggestPositive);
const redPalette = colorPalette(darkestRed, lighestRed, Math.abs(biggestNegative) + 1);
const fullPalette = [];
for (const datum of data) {
if (datum > 0) {
fullPalette.push([greenPalette[datum - 1]]);
} else if (datum < 0) {
fullPalette.push([redPalette[Math.abs(datum) - 1]]);
} else if (datum == 0 || isNaN(datum)) {
fullPalette.push(['#ffffff']);
}
}
range.setBackgrounds(fullPalette);
}
function customRange() {
const ui = SpreadsheetApp.getUi();
result = ui.prompt("Please enter a range");
parseData(result.getResponseText());
}
function colorPalette(darkestColor, lightestColor, colorSteps) {
const firstColor = hexToRGB(darkestColor);
const lastColor = hexToRGB(lightestColor);
let blending = 0;
const gradientColors = [];
for (i = 0; i < colorSteps; i++) {
const color = [];
blending += (1 / colorSteps);
color[0] = firstColor[0] * blending + (1 - blending) * lastColor[0];
color[1] = firstColor[1] * blending + (1 - blending) * lastColor[1];
color[2] = firstColor[2] * blending + (1 - blending) * lastColor[2];
gradientColors.push(rgbToHex(color));
}
return gradientColors;
}
function hexToRGB(hex) {
const color = [];
color[0] = Number.parseInt((removeNumeralSymbol(hex)).slice(0, 2), 16);
color[1] = Number.parseInt((removeNumeralSymbol(hex)).slice(2, 4), 16);
color[2] = Number.parseInt((removeNumeralSymbol(hex)).slice(4, 6), 16);
return color;
}
function removeNumeralSymbol(hex) {
return (hex.charAt(0) == '#') ? hex.slice(1, 7) : hex;
}
function rgbToHex(rgb) {
return '#' + hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
function hex(c) {
const pool = '0123456789abcdef';
let integer = Number.parseInt(c, 10);
if (integer === 0 || isNaN(c)) {
return '00';
}
integer = Math.round(Math.min(Math.max(0, integer), 255));
return pool.charAt((integer - integer % 16) / 16) + pool.charAt(integer % 16);
}

Why I cant solve this puzzle?

Im tring to solve this puzzle by using dart lang but I didint solve it and I got large number + error! There is an puzzle image to understand it from here
can you help or give me a tip to solve this puzzle ~!
See full code :
import 'dart:math';
void main() {
var value;
int loob = 0;
do {
var z = new Random().nextInt(20);
var x = new Random().nextInt(20);
var y = new Random().nextInt(20);
var n = new Random().nextInt(20);
if (z - x == 9) {
print('DONE LOOB1 Z = $z and X = $x');
do {
var x = new Random().nextInt(20);
var n = new Random().nextInt(20);
if (x + n == 2) {
print('DONE LOOB2 X = $x and n = $n ');
do {
var n = new Random().nextInt(20);
var y = new Random().nextInt(20);
if (y - n == 14) {
print('DONE LOOB3 y = $y and n = $n ');
do {
var z = new Random().nextInt(20);
var y = new Random().nextInt(20);
if (z - y == 12) {
print('DONE LOOB4 z = $z and y = $y ');
value = 1;
} else {}
} while (value != 1);
} else {}
} while (value != 1);
value = 1;
} else {}
} while (value != 1);
value = 1;
} else {
null;
}
print(++loob);
} while (value != 1);
}
reslate code :
DONE LOOB1 Z = 11 and X = 2
DONE LOOB2 X = 2 and n = 0
DONE LOOB3 y = 14 and n = 0
DONE LOOB4 z = 17 and y = 5
Finshed
this is your algorithm issue, you are adding 0.1 to your variable every step, and it means all numbers are equal in the end you must create two mathematical equations and two unknown values and then solve them. this is the main approach to solve such problems.
Assume this picture like these Equations:
x - y = 9
x + n = 2
y - n = 14
z - y = 12
now you have 4 equations and 4 unknown.
you can solve this equation by this (Matrix manipulation) or this (substitution one unknown with another) on method.

Gaussian random numbers with swift 2.1

I'm trying to update an old objective-c project to swift. I need to generate gaussian random numbers. In objective-c I used this:
double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;
if(phase == 0) {
do {
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else
X = V2 * sqrt(-2 * log(S) / S);
phase = 1 - phase;
return X;
}
However this doesn't translate well into swift. Anybody know a way to generate gaussian random numbers given a mean and a standard deviation in sfift 2.1?
Note that as you have defined it, you want gaussRand to be a computed property. Computed properties in Swift cannot store other properties, so in the example of a Swift version of your Box-Muller transformation method implementation, I've wrapped the computed property gaussRand in a class, and kept s, v2 and cachedNumberExists as stored properties in this same class, allowing for every 2nd call gaussRand to return the cached result from previous one.
class MyRandomGenerator {
// stored properties
var s : Double = 0.0
var v2 : Double = 0.0
var cachedNumberExists = false
// (read-only) computed properties
var gaussRand : Double {
var u1, u2, v1, x : Double
if !cachedNumberExists {
repeat {
u1 = Double(arc4random()) / Double(UINT32_MAX)
u2 = Double(arc4random()) / Double(UINT32_MAX)
v1 = 2 * u1 - 1;
v2 = 2 * u2 - 1;
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0)
x = v1 * sqrt(-2 * log(s) / s);
}
else {
x = v2 * sqrt(-2 * log(s) / s);
}
cachedNumberExists = !cachedNumberExists
return x
}
}
We assert that we get the expected results:
// Assert expected results
var myRandomGenerator = MyRandomGenerator()
let numGaussNumbers = 1000
var myGaussArr = [Double](count: numGaussNumbers, repeatedValue: 0.0)
for (i,_) in myGaussArr.enumerate() { myGaussArr[i] = myRandomGenerator.gaussRand }
let myMean = myGaussArr.reduce(0.0, combine: +)/Double(numGaussNumbers) // 0.0.. OK
let myVar = myGaussArr.map { pow(($0 - myMean), 2) }.reduce(0.0, combine: +)/Double(numGaussNumbers) // ~1, O
print("(\(myMean),\(myVar))") // ~(0,1), OK
OK.
Here is a translation of Java's very efficient Random.nextGaussian() method into Swift:
private var nextNextGaussian: Double? = {
srand48(Int(arc4random())) //initialize drand48 buffer at most once
return nil
}()
func nextGaussian() -> Double {
if let gaussian = nextNextGaussian {
nextNextGaussian = nil
return gaussian
} else {
var v1, v2, s: Double
repeat {
v1 = 2 * drand48() - 1
v2 = 2 * drand48() - 1
s = v1 * v1 + v2 * v2
} while s >= 1 || s == 0
let multiplier = sqrt(-2 * log(s)/s)
nextNextGaussian = v2 * multiplier
return v1 * multiplier
}
}
Now, to generate a gaussian random number given a mean and standard deviation, just do:
let myGaussian = nextGaussian() * myStandardDeviation + myMean

Highcharts Scatter Plot - How to Fix Overlapping Data Labels?

I have seen many posts on this topic, but it doesn't seem the issue has ever been properly addressed.
We have a large scatter with about 30 points on it (nothing overwhelming). But in certain cases, the dots will be very close together or overlapping (not much we can really do about that, I guess).
The main problem is that we want the data labels visible at all times, and these data labels are overlapping when the points are close to each other.
We have tried allowOverlap: false, but that's not really what we need/want. Our ideal outcome is allowing all datalabels to be displayed on screen inside the scatter while still being able to read each one at all times.
Do we fix this by adjusting the separation of the dots or by adjusting the separation/padding of the datalabels? Any suggestions? Thank you.
I haven't found a working configuration solution of this problem from Highcharts (although I cannot guarantee there isn't one in latest version). However there are some algorithms for acceptable randomization of the labels coordinates that split data labels.
Here are some useful links that could help you with the algorithm:
wordcloud package in R (cloud.R is the file containing the algorithm)
direct labels package in R
And some dummy pseudo code translation in JavaScript of the R code would be:
splitLabels: function() {
// Create an array of x-es and y-es that indicate where your data lie
var xArr = getAllDataX();
var yArr = getAllDataY();
var labelsInfo = {};
this.chartSeries.forEach(function(el) {
var text = el.data.name;
labelsInfo[el.data.id] = {
height: getHeight(text),
width: getWidth(text),
text: text
};
}, this);
var sdx = getStandardDeviation(xArr);
var sdy = getStandardDeviation(yArr);
if(sdx === 0) sdx = 1;
if(sdy === 0) sdy = 1;
var boxes = [];
var xlim = [], ylim = [];
xlim[0] = this.chart.xAxis[0].getExtremes().min;
xlim[1] = this.chart.xAxis[0].getExtremes().max;
ylim[0] = this.chart.yAxis[0].getExtremes().min;
ylim[1] = this.chart.yAxis[0].getExtremes().max;
for (var i = 0; i < data.length; i++) {
var pointX = data[i].x;
var pointY = data[i].y;
if (pointX<xlim[0] || pointY<ylim[0] || pointX>xlim[1] || pointY>ylim[1]) continue;
var theta = Math.random() * 2 * Math.PI,
x1 = data[i].x,
x0 = data[i].x,
y1 = data[i].y,
y0 = data[i].y,
width = labelsInfo[data[i].id].width,
height = labelsInfo[data[i].id].height ,
tstep = Math.abs(xlim[1] - xlim[0]) > Math.abs(ylim[1] - ylim[0]) ? Math.abs(ylim[1] - ylim[0]) / 100 : Math.abs(xlim[1] - xlim[0]) / 100,
rstep = Math.abs(xlim[1] - xlim[0]) > Math.abs(ylim[1] - ylim[0]) ? Math.abs(ylim[1] - ylim[0]) / 100 : Math.abs(xlim[1] - xlim[0]) / 100,
r = 0;
var isOverlapped = true;
while(isOverlapped) {
if((!hasOverlapped(x1-0.5*width, y1-0.5*height, width, height, boxes)
&& x1-0.5*width>xlim[0] && y1-0.5*height>ylim[0] && x1+0.5*width<xlim[1] && y1+0.5*height<ylim[1]) )
{
boxes.push({
leftX: x1-0.5*width,
bottomY: y1-0.5*height,
width: width,
height: height,
icon: false,
id: data[i].id,
name: labelsInfo[data[i].id].text
});
data[i].update({
name: labelsInfo[data[i].id].text,
dataLabels: {
x: (x1 - data[i].x),
y: (data[i].y - y1)
}
}, false);
isOverlapped = false;
} else {
theta = theta+tstep;
r = r + rstep*tstep/(2*Math.PI);
x1 = x0+sdx*r*Math.cos(theta);
y1 = y0+sdy*r*Math.sin(theta);
}
}
}
// You may have to redraw the chart here
},
You can call this function on redraw or optimized to call it less often.
Please note that if you have some big points or shapes or icons indicating where your data items lie you will have to check if any of the proposed solutions does not interfere(overlap) with the icons as well.
You can try to adapt this algorithm:
function StaggerDataLabels(series) {
sc = series.length;
if (sc < 2) return;
for (s = 1; s < sc; s++) {
var s1 = series[s - 1].points,
s2 = series[s].points,
l = s1.length,
diff, h;
for (i = 0; i < l; i++) {
if (s1[i].dataLabel && s2[i].dataLabel) {
diff = s1[i].dataLabel.y - s2[i].dataLabel.y;
h = s1[i].dataLabel.height + 2;
if (isLabelOnLabel(s1[i].dataLabel, s2[i].dataLabel)) {
if (diff < 0) s1[i].dataLabel.translate(s1[i].dataLabel.translateX, s1[i].dataLabel.translateY - (h + diff));
else s2[i].dataLabel.translate(s2[i].dataLabel.translateX, s2[i].dataLabel.translateY - (h - diff));
}
}
}
}
}
//compares two datalabels and returns true if they overlap
function isLabelOnLabel(a, b) {
var al = a.x - (a.width / 2);
var ar = a.x + (a.width / 2);
var bl = b.x - (b.width / 2);
var br = b.x + (b.width / 2);
var at = a.y;
var ab = a.y + a.height;
var bt = b.y;
var bb = b.y + b.height;
if (bl > ar || br < al) {
return false;
} //overlap not possible
if (bt > ab || bb < at) {
return false;
} //overlap not possible
if (bl > al && bl < ar) {
return true;
}
if (br > al && br < ar) {
return true;
}
if (bt > at && bt < ab) {
return true;
}
if (bb > at && bb < ab) {
return true;
}
return false;
}
http://jsfiddle.net/menXU/6/

Calculate factorial of a decimal (i.e. Gamma function) on iOS

I need to calculate the factorial of a decimal number, say 6.4, on iOS. I tried
double myFactorial = gamma(6.4);
But get the error "'gamma is unavailable': not avaiable on iOS". Is there a way to add the gamma function into iOS?
Have you tried:
tgamma(6.4)
I see it working in my code.
There's also:
double tgamma (double x)
float tgammaf (float x)
long double tgammal (long double x)
you can try like this logic may be this will well you.
- (int)factorial:(int)operand
{
if`enter code here`(operand < 0)
return -1;
else if (operand > 1)
return operand * [self factorial:operand - 1];
else
return 1;
}
and then
- (double)factorial:(double)operand
{
double output = operand;
if (output == 0) output = 1; // factorial of 0 is 1
else if (output < 0) output = NAN;
else if (output > 0)
{
if (fmod(output, floor(output)) == 0) // integer
output = round(exp(lgamma(output + 1)));
else // natural number
output = exp(lgamma(output + 1));
}
return output;
}
- (double)n:(double)n chooseR:(double)r
{
return round(exp((lgamma(n+1)) - (lgamma(r+1) + lgamma(n-r+1))));
}
- (double)n:(double)n pickR:(double)r
{
return round(exp(lgamma(n+1) - lgamma(n-r+1)));
}

Resources