This question already has answers here:
Crash when casting the result of arc4random() to Int
(7 answers)
Closed 8 years ago.
I'm having problems with this drawRandomCard function.
It works just like it should for some time, but eventually it crashes the application.
Here is the code:
import Foundation
var cardDeck = Array<PlayingCard>()
class Deck {
func addCard(card : PlayingCard , atTop : Bool = false){
if atTop {
cardDeck.insert(card, atIndex: 0);
}else{
cardDeck += card
}
}
func drawRandomCard() -> PlayingCard{
var card = PlayingCard()
var randomNumber : Int = Int(arc4random()) % (cardDeck.count - 1)
card = cardDeck[randomNumber]
cardDeck.removeAtIndex(randomNumber)
return card
}
}
Use arc4random_uniform to avoid modulo bias. Like following:
let randomNumber = arc4random_uniform(150)
For your example, it will be:
let randomNumber = Int(arc4random_uniform(UInt32(cardDeck.count)))
Try this: Int(rand()) instead of arc4random()
Related
I'm trying to select 2 random items out of a list using the RNG class. The problem is occasionally I get the same 2 numbers and I'd like them to be unique. I tried using a while loop to get another number if the it's the same as the last one but adding even a simple while loop results in an "Exceeded prepaid gas" error. What am I not understanding?
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
for(let i = 0; i < numItemsWanted; i++) {
var r = rng.next()
while (r == rng.last()) {
r = rng.next()
}
newList.push(oldList[r])
}
Working:
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
let r = rng.next()
let last = r + 1
for(let i = 0; i < numItemsWanted; i++) {
newList.push(oldList[r])
last = r
r = rng.next()
while (r == last) {
r = rng.next()
}
}
this is about near-sdk-as, the smart contract development kit for AssemblyScript on the NEAR platform
you can see how RNG is used in this example
https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/ff6cddaa8cac4d8fe29dd1a19b38a6e3c7045363/src/lottery/assembly/lottery.ts#L12-L13
class Lottery {
private chance: f64 = 0.20
play(): bool {
const rng = new RNG<u32>(1, u32.MAX_VALUE);
const roll = rng.next();
logging.log("roll: " + roll.toString());
return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
}
}
and how the constructor is implemented here:
https://github.com/near/near-sdk-as/blob/f3707a1672d6da6f6d6a75cd645f8cbdacdaf495/sdk-core/assembly/math.ts#L152
the first argument is the length of the buffer holding random numbers generated from the seed. you can use the next() method to get more numbers from this buffer with each call
export class RNG<T> {
constructor(len: u32, public max: u32 = 10_000) {
let real_len = len * sizeof<T>();
this.buffer = math.randomBuffer(real_len);
this._last = this.get(0);
}
next(): T {}
}
If you remove the item from oldList once picked, it would be imposible to picked it again.
Another aproach is to shuffle your oldList and then pick the first two items.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
A recursive call while implementing merge sort throws an error. I tried using debug macros to see if its some memory restriction without luck.
fn merge<T: PartialOrd>(mut v: Vec<T>) -> Vec<T> {
if v.len() < 1 {
return v;
}
let mut res = Vec::with_capacity(v.len());
let b = v.split_off(v.len() / 2);
let a = merge(v);
let b = merge(b);
let mut a_it = a.into_iter();
let mut b_it = b.into_iter();
let mut a_curr = a_it.next();
let mut b_curr = b_it.next();
loop {
match a_curr {
Some(ref a_val) => match b_curr {
Some(ref b_val) => {
if a_val < b_val {
res.push(a_curr.take().unwrap());
a_curr = a_it.next()
} else {
res.push(b_curr.take().unwrap());
b_curr = b_it.next();
}
}
None => {
res.push(a_curr.take().unwrap());
res.extend(a_it);
return res;
}
},
None => {
if let Some(b_val) = b_curr {
res.push(b_val)
}
res.extend(b_it);
return res;
}
}
}
}
fn main() {
let v = vec![9, 7, 4, 6, 5, 2, 1, 11];
let x = merge(v);
println!("{:?}", x);
}
thread 'main' has overflowed its stack
error: process didn't exit successfully: `target\debug\tescode.exe` (exit code: 0xc00000fd, STATUS_STACK_OVERFLOW)
You have a stack overflow because you perform an infinite number of recursive calls. This is caused by the fact that your exit criteria is incorrect; use less-than-or-equal instead:
if v.len() <= 1 {
return v;
}
I have been doing printing job with Thermal Printer Image Printing on portable thermal printer for weeks and this is code I got for Image Printing.
public static byte[] GetByteImage(Bitmap bm, int BitmapWidth)
{
BitmapData data = GetGreyScaledBitmapData(bm, BitmapWidth);
BitArray dots = data.Dots;
string t = data.Width.ToString();
byte[] width = BitConverter.GetBytes(data.Width);
int offset = 0;
MemoryStream stream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(stream);
//Line spacing
bw.Write((char)0x1B);
bw.Write('3');
bw.Write((byte)0);
while (offset < data.Height)
{
//Declare printer to print image mode
bw.Write((char)0x1B);
bw.Write('*');
bw.Write((byte)33);
bw.Write(width[0]);
bw.Write(width[1]);
for (int x = 0; x < data.Width; ++x)
{
for (int k = 0; k < 3; ++k)
{
byte slice = 0;
for (int b = 0; b < 8; ++b)
{
int y = (((offset / 8) + k) * 8) + b;
int i = (y * data.Width) + x;
bool v = false;
if (i < dots.Length)
{
v = dots[i];
}
slice |= (byte)((v ? 1 : 0) << (7 - b));
}
bw.Write(slice);
}
}
offset += 24;
bw.Write((char)0x0A);
}
bw.Write((char)0x1B);
bw.Write('3');
bw.Write((byte)0);
bw.Flush();
byte[] bytes = stream.ToArray();
return bytes;
}
public static BitmapData GetGreyScaledBitmapData(Bitmap bmpFileName, double imgsize)
{
using (var bitmap = (Bitmap)(bmpFileName))
{
var threshold = 127;
var index = 0;
double multiplier = imgsize;
double scale = (double)(multiplier / (double)bitmap.Width);
int xheight = (int)(bitmap.Height * scale);
int xwidth = (int)(bitmap.Width * scale);
var dimensions = xwidth * xheight;
var dots = new BitArray(dimensions);
for (var y = 0; y < xheight; y++)
{
for (var x = 0; x < xwidth; x++)
{
var _x = (int)(x / scale);
var _y = (int)(y / scale);
Android.Graphics.Color color = new Android.Graphics.Color(bitmap.GetPixel(_x, _y));
var luminance = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
dots[index] = (luminance < threshold);
index++;
}
}
return new BitmapData()
{
Dots = dots,
Height = (int)(bitmap.Height * scale),
Width = (int)(bitmap.Width * scale)
};
}
}
public class BitmapData
{
public BitArray Dots
{
get;
set;
}
public int Height
{
get;
set;
}
public int Width
{
get;
set;
}
}
The problem is, it print very slow and make jerking sound while printing.
Another problem is, the method of image converting to Grey Scale is a bit slow.
And when I test with other apps I found that they have no jerking sound and almost instantly print image after clicked print button.
Is there a way to improve above code so it can print smoothly ?
This is the app I tested Printer Lab - Thermal printer manager
The Thermal Printer I used RPP300 72mm Mobile Printer
The ESC * command you are using prints every 24 dots in height.
Then, as you feel the problem, it will be jerky and slow print.
Please use a combination of GS * and GS / commands to improve it.
Details of their specifications are described on pages 24 to 26 of the Thermal Mobile Printer Command Set Manual.
In Addition:
By the way, I was overlooking another command.
It would be easier for us to create the data that we will send.
However, smooth printing depends on the printer performance and communication line speed.
That command is GS v 0. It is described on pages 32 and 33 of the manual.
The program in this article is a bit image data conversion process for FS q and GS (L / GS 8 L commands, but it can also be used for GS * commands. Please try it.
Convert raster byte[] image data to column Format in C#
Finally got a solution. I was really dumb back then. Just ask your printer manufacturer company for SDK or find SDK from other printer manufacturer.
I need to start the same random number list over every execution of my app.
srand/rand do not exist anymore. What should I do then?
private extension Array {
private func randomValues(_ seed: UInt32, num: Int) -> [Element] {
srand (seed)
var indices = [Int]()
indices.reserveCapacity(num)
let range = 0..<self.count
for _ in 0..<num {
var random = 0
repeat {
random = randomNumberInRange(range)
} while indices.contains(random)
indices.append(random)
}
return indices.map { self[$0] }
}
You can use
srand48(seed) and drand48() in Swift3.
Unless you're developing with Swift for non-Apple platforms, you can get a much better randomization API in GameplayKit: several algorithms (trade randomness vs speed), seedable, distribution control, etc.
I can't find a way to use seeded random in Swift 3 Beta 1. Had to write a silly wrapper function in C:
// ----------------------------------------------
// my_random.h
// ----------------------------------------------
#ifndef my_random_h
#define my_random_h
#include <stdio.h>
#endif /* my_random_h */
long next_random();
// ----------------------------------------------
// my_random.c
// ----------------------------------------------
#include <stdlib.h>
#include "my_random.h"
long next_random() {
return random();
}
You can use the bridging header to import it into Swift. Then you can call it in Swift like this:
srandom(42)
for _ in 0..<10 {
let x = next_random()
print(x)
}
random is better than rand. Read the man pages for discussion on these 2 functions.
Edit:
A workaround, as #riskter suggested, is to use GameKit:
import GameKit
let seed = Data(bytes: [42]) // Use any array of [UInt8]
let source = GKARC4RandomSource(seed: seed)
for _ in 0..<10 {
let x = source.nextInt()
print(x)
}
For a simple repeatable random list try using a Linear Congruential Generator:
import Foundation
class LinearCongruntialGenerator
{
var state = 0 //seed of 0 by default
let a, c, m, shift: Int
//we will use microsoft random by default
init() {
self.a = 214013
self.c = 2531011
self.m = Int(pow(2.0, 31.0)) //2^31 or 2147483648
self.shift = 16
}
init(a: Int, c: Int, m: Int, shift: Int) {
self.a = a
self.c = c
self.m = m //2^31 or 2147483648
self.shift = shift
}
func seed(seed: Int) -> Void {
state = seed;
}
func random() -> Int {
state = (a * state + c) % m
return state >> shift
}
}
let microsoftLinearCongruntialGenerator = LinearCongruntialGenerator()
print("Microsft Rand:")
for i in 0...10
{
print(microsoftLinearCongruntialGenerator.random())
}
More info here:
https://rosettacode.org/wiki/Linear_congruential_generator
I just happened to put this together for Swift 4. I am aware Swift 4.2 has new random extensions that are different from this, but like the OP, I needed them to be seedable during testing. Maybe someone will find it helpful. If you don't seed it, it will use arc4random, otherwise it will use drand48. It avoids mod bias both ways.
import Foundation
class Random {
static var number = unseededGenerator // the current generator
/**
* returns a random Int 0..<n
**/
func get(anIntLessThan n: Int) -> Int {
return generatingFunction(n)
}
class func set(seed: Int) {
number = seedableGenerator
srand48(seed)
}
// Don't normally need to call the rest
typealias GeneratingFunction = (Int) -> Int
static let unseededGenerator = Random(){
Int(arc4random_uniform(UInt32($0)))
}
static let seedableGenerator = Random(){
Int(drand48() * Double($0))
}
init(_ gf: #escaping GeneratingFunction) {
self.generatingFunction = gf
}
private let generatingFunction: GeneratingFunction
}
func randomTest() {
Random.set(seed: 65) // comment this line out for unseeded
for _ in 0..<10 {
print(
Random.number.get(anIntLessThan: 2),
terminator: " "
)
}
}
// Run
randomTest()
The normal Dart Random class supports Random values up to (1 << 32) - 1, which is indeed quite big, but how can I generate numbers, which are much larger than this? (With much larger I mean ((1 << 32) - 1) * 10^50 or something like that.
You can do this by combining multiple random numbers; for example if you want a 64bit random number, you could do:
var r = new Random();
var random1 = r.nextInt(pow(2, 32));
var random2 = r.nextInt(pow(2, 32));
var bigRandom = (random1 << 32) | random2;
print(bigRandom); // 64bit random number
Be aware; if you're running outside of the Dart VM (using dart2js), then you'll be bound by JavaScripts number restrictions. If you need rally big numbers in JavaScript, you'll need a library (and the performance will likely suck).
I did is as rossum suggested: I generated numbers (in decimal system) concatenated them and parsed them and looked if they were among the allowed values ( < maxValue). Algorithm is:
int nextInt(int max) {
int digits = max.toString().length;
var out = 0;
do {
var str = "";
for (int i = 0; i < digits; i++) {
str += this._random.nextInt(10).toString();
}
out = int.parse(str);
} while (out < max);
return out;
}
Here is my implementation in case someone needs it in the future:
class BigRandom {
static final rnd = new Random();
static int nextInt(int max) {
if (max > pow(2, 32)) {
var charCount = max.toString().length;
var seperator = (charCount / 2).floor();
var leftHalf = int.parse(max.toString().substring(0, seperator));
var rightHalf = int.parse(max.toString().substring(seperator));
var rndLeft = nextInt(leftHalf);
var rndRight = nextInt(rightHalf);
return int.parse('$rndLeft$rndRight');
} else {
return rnd.nextInt(max);
}
}
}