Swift newbie here. I am trying to convert some of my python code to swift and im stuck at the point where I need to split a string of letters into and array with each item being 3 letters:
For example my python code is as follows:
name = "ATAGASSTSSGASTA"
threes =[]
for start in range(0, len(name),3):
threes.append(name[start : start + 3])
print threes
For swift ive come as far as this:
var name = "ATAGASSTSSGASTA"
let namearr = Array(name)
let threes = []
threes.append(namearr[0...3])
This gives me an error.
I realize there may be an much easier way to do this, but I have not been able to find anything in my research. Any help is appreciated!
An easy and Swifty way to do this is to map an array of chars using the stride and advance functions:
let name = Array("ATAGASSTSSGASTA")
let splitName = map(stride(from: 0, to: name.count, by: 3)) {
String(name[$0..<advance($0, 3, name.count)])
}
This is pretty verbose, but it does the job:
let name = "ATAGASSTSSGASTA"
let array = reduce(name, [String]()) {
switch $0.last {
case .Some(let last) where countElements(last) < 3:
var array = $0
array[array.endIndex-1].append($1)
return array
case .Some(_), .None:
return $0 + [String($1)]
}
}
Edit: In Swift 1.2, I think countElements has changed to just count. Not sure, don't have it yet, but the documents make it look that way.
var nucString = "aatttatatatattgctgatctgatctEOS"
let nucArrayChar = Array(nucString)
var nucArray: [String] = []
var counter: Int = nucArrayChar.count
if counter % 3 == 0 {
for var startNo = 0; startNo < counter; startNo += 3 {
println("\(nucArray)\(startNo)")
nucArray.append(String(nucArrayChar[(startNo)...(startNo + 2)]))
}
}
Related
I've had a gander and haven't found a satisfactory answer. In JavaScript it's possible to simply add a method to an array alla:
const makeGrid = (size) => {
let grid = [];
for (let i = 0; i < size; i++) {
let row = new Array(size).fill(0);
grid.push(row);
}
grid.toggleChunkPlaced = (x, y) => {
grid[y][x] === 0 ? (grid[y][x] = 1) : (grid[y][x] = 0);
};
return grid
};
However I'm not sure if it is possible (or recommended) to do in Python - my best guess is something like:
def make_grid(size):
grid = []
for i in size:
row = [0]*size
grid.append(row)
grid.toggle_chunk_placed = lambda x, y: grid[y][x] = 1 if grid[y][x] == 0 else grid[y][x] = 0
return grid
Nope. You can't do that with a list. It is possible if you really badly want it to be possible but I don't think that's the case. If you do want it, I'll have to write an answer that would probably only get downvotes 😅. What I mean is, there is a better way. – Diptangsu Goswami
I'm trying to do choices based on their weight/probability
this is what I had in python:
import random
myChoiceList = ["Attack", "Heal", "Amplify", "Defense"]
myWeights = [70, 0, 15, 15] // % probability = 100% Ex. Attack has 70% of selection
print(random.choices(myChoicelist , weights = myWeights, k = 1))
I want to do the same thing in c#, how does one do that?
does C# have any methods similar to random.choices() all I know is random.Next()
*this python code works fine randome.choice takes in (sequence, weights, k)
sequence: values,
weights: A list were you can weigh the possibility for each value,
k: the length of the returned list,
I'm looking to do the same for C#,
choose values based on there probability
There is nothing built into C# like this, however, it's not that hard to add an extension method to recreate the same basic behavior:
static class RandomUtils
{
public static string Choice(this Random rnd, IEnumerable<string> choices, IEnumerable<int> weights)
{
var cumulativeWeight = new List<int>();
int last = 0;
foreach (var cur in weights)
{
last += cur;
cumulativeWeight.Add(last);
}
int choice = rnd.Next(last);
int i = 0;
foreach (var cur in choices)
{
if (choice < cumulativeWeight[i])
{
return cur;
}
i++;
}
return null;
}
}
Then you can call it in a similar way as the Python version:
string[] choices = { "Attack", "Heal", "Amplify", "Defense" };
int[] weights = { 70, 0, 15, 15 };
Random rnd = new Random();
Console.WriteLine(rnd.Choice(choices, weights));
you can get random.next(0,100), then choose the relevant item with a simple switch case or something. your domains will be like this , [0-70 , 70-85, 85-100]. let me know if you need full code.
Random ran = new Random();
int probability = ran.Next(0, 100);
string s;
if (probability == 0)
s = "Heal";
else if (probability <= 70)
s = "Attack";
else if (probability <= 85)
s = "Amplify";
else if (probability <= 100)
s = "Defense";
I am trying to write a similar code in Python, but I am new to it.
int counts[] = { 0, 0, 0, 0, 0 };
for (int i = 0; i < groups; i++) {
int groups_size;
scanf(" %d", &groups_size);
counts[groups_size] += 1;
}
Please note that it does not all the save the numbers into memory.
I tried to do this in Python as:
for group in range(groups):
num = int(input().strip())
counts[num] += 1
This does not work. When I enter 1 2 3 4 5 into terminal, I get ValueError: invalid literal for int() with base 10: '1 2 3 4 5'.
Is there a way of doing this in Python the same as I did in C?
In python, it will not automatically take one number and then loop for the other. You input() command will read the whole line at once. So, what you can do is read the whole line in a string and then split it into a list as follows -
str = input()
num = list(map(int,str.split()))
Now you have all the input given by user stored in the num variable. You can just iterate over it and complete your process as follows -
counts = [0]*5 #assuming you want it to be of size 5 as in your question
for inp in num :
counts[inp] = counts[inp] + 1
Hope this helps!
I'm trying to rewrite this function:
def smoothen_fast(heightProfile, travelTime):
smoothingInterval = 30 * travelTime
heightProfile.extend([heightProfile[-1]]*smoothingInterval)
# Get the mean of first `smoothingInterval` items
first_mean = sum(heightProfile[:smoothingInterval]) / smoothingInterval
newHeightProfile = [first_mean]
for i in xrange(len(heightProfile)-smoothingInterval-1):
prev = heightProfile[i] # the item to be subtracted from the sum
new = heightProfile[i+smoothingInterval] # item to be added
# Calculate the sum of previous items by multiplying
# last mean with smoothingInterval
prev_sum = newHeightProfile[-1] * smoothingInterval
new_sum = prev_sum - prev + new
mean = new_sum / smoothingInterval
newHeightProfile.append(mean)
return newHeightProfile
as embedded C++ Code:
import scipy.weave as weave
heightProfile = [0.14,0.148,1.423,4.5]
heightProfileSize = len(heightProfile)
travelTime = 3
code = r"""
#include <string.h>
int smoothingInterval = 30 * travelTime;
double *heightProfileR = new double[heightProfileSize+smoothingInterval];
for (int i = 0; i < heightProfileSize; i++)
{
heightProfileR[i] = heightProfile[i];
}
for (int i = 0; i < smoothingInterval; i++)
{
heightProfileR[heightProfileSize+i] = -1;
}
double mean = 0;
for (int i = 0; i < smoothingInterval; i++)
{
mean += heightProfileR[i];
}
mean = mean/smoothingInterval;
double *heightProfileNew = new double[heightProfileSize-smoothingInterval];
for (int i = 0; i < heightProfileSize-smoothingInterval-1; i++)
{
double prev = heightProfileR[i];
double newp = heightProfile[i+smoothingInterval];
double prev_sum = heightProfileNew[i] * smoothingInterval;
double new_sum = prev_sum - prev + newp;
double meanp = new_sum / smoothingInterval;
heightProfileNew[i+1] = meanp;
}
return_val = Py::new_reference_to(Py::Double(heightProfileNew));
"""
d = weave.inline(code,['heightProfile','heightProfileSize','travelTime'])
As a return type i need the heightProfileNew. I need the access it like a list in Python later.
I look at these examples:
http://docs.scipy.org/doc/scipy/reference/tutorial/weave.html
He keeps telling me that he doesn't know Py::, but in the examples there are no Py-Includes?
I know, the question is old, but I think it is still interesting.
Assuming your using weave to improve computation speed and that you know the length of your output beforehand, I suggest that you create the result before calling inline. That way you can create the result variable in python (very easy). I would also suggest using a nd.ndarray as a result because it makes shure you use the right datatype. You can iterate ndarrays in python the same way you iterate lists.
import numpy as np
heightProfileArray = np.array(heightprofile)
# heightProfileArray = np.array(heightprofile, dtype = np.float32) if you want to make shure you have the right datatype. Another choice would be np.float64
resultArray = np.zeros_like(heightProfileArray) # same array size and data type but filled with zeros
[..]
weave.inline(code,['heightProfile','heightProfileSize','travelTime','resultArray'])
for element in resultArray:
print element
In your C++-code you can then just assign values to elements of that array:
[..]
resultArray[i+1] = 5.5;
[..]
I need an algorithm to split a list of values into such chunks, that sum of values in every chunk is (approximately) equals (its some variation of Knapsack problem, I suppose)
So, for example [1, 2, 1, 4, 10, 3, 8] => [[8, 2], [10], [1, 3, 1, 4]]
Chunks of equal lengths are preferred, but it's not a constraint.
Python is preferred language, but others are welcome as well
Edit: number of chunks is defined
Greedy:
1. Order the available items descending.
2. Create N empty groups
3. Start adding the items one at a time into the group that has the smallest sum in it.
I think in most real life situations this should be enough.
Based on #Alin Purcaru answer and #amit remarks, I wrote code (Python 3.1). It has, as far as I tested, linear performance (both for number of items and number of chunks, so finally it's O(N * M)). I avoid sorting the list every time, keeping current sum of values for every chunk in a dict (can be less practical with greater number of chunks)
import time, random
def split_chunks(l, n):
"""
Splits list l into n chunks with approximately equals sum of values
see http://stackoverflow.com/questions/6855394/splitting-list-in-chunks-of-balanced-weight
"""
result = [[] for i in range(n)]
sums = {i:0 for i in range(n)}
c = 0
for e in l:
for i in sums:
if c == sums[i]:
result[i].append(e)
break
sums[i] += e
c = min(sums.values())
return result
if __name__ == '__main__':
MIN_VALUE = 0
MAX_VALUE = 20000000
ITEMS = 50000
CHUNKS = 256
l =[random.randint(MIN_VALUE, MAX_VALUE ) for i in range(ITEMS)]
t = time.time()
r = split_chunks(l, CHUNKS)
print(ITEMS, CHUNKS, time.time() - t)
Just because, you know, we can, the same code in PHP 5.3 (2 - 3 times slower than Python 3.1):
function split_chunks($l, $n){
$result = array_fill(0, $n, array());
$sums = array_fill(0, $n, 0);
$c = 0;
foreach ($l as $e){
foreach ($sums as $i=>$sum){
if ($c == $sum){
$result[$i][] = $e;
break;
} // if
} // foreach
$sums[$i] += $e;
$c = min($sums);
} // foreach
return $result;
}
define('MIN_VALUE',0);
define('MAX_VALUE',20000000);
define('ITEMS',50000);
define('CHUNKS',128);
$l = array();
for ($i=0; $i<ITEMS; $i++){
$l[] = rand(MIN_VALUE, MAX_VALUE);
}
$t = microtime(true);
$r = split_chunks($l, CHUNKS);
$t = microtime(true) - $t;
print(ITEMS. ' ' . CHUNKS .' ' . $t . ' ');
This will be faster and a little cleaner (based on above ideas!)
def split_chunks2(l, n):
result = [[] for i in range(n)]
sums = [0]*n
i = 0
for e in l:
result[i].append(e)
sums[i] += e
i = sums.index(min(sums))
return result
you may want to use Artificial Intelligence tools for the problem.
first define your problem
States={(c1,c2,...,ck) | c1,...,ck are subgroups of your problem , and union(c1,..,ck)=S }
successors((c1,...,ck)) = {switch one element from one sub list to another }
utility(c1,...,ck) = max{sum(c1),sum(c2)...} - min{sum(c1),sum(c2),...}
now, you can use steepest ascent hill climbing with random-restarts.
this algorithm will be anytime, meaning you can start searching, and when time's up - stop it, and you will get the best result so far. the result will be better as run time increased.
Scala version of foxtrotmikew answer:
def workload_balancer(element_list: Seq[(Long, Any)], partitions: Int): Seq[Seq[(Long, Any)]] = {
val result = scala.collection.mutable.Seq.fill(partitions)(null : Seq[(Long, Any)])
val index = (0 to element_list.size-1)
val weights = scala.collection.mutable.Seq.fill(partitions)(0l)
(0 to partitions-1).foreach( x => weights(x) = 0 )
var i = 0
for (e <- element_list){
result(i) = if(result(i) == null) Seq(e) else result(i) ++: Seq(e)
weights(i) = weights(i) + e._1
i = weights.indexOf( weights.min )
}
result.toSeq
}
element_list should be (weight : Long, Object : Any), then you can order and split objects into different workloads (result). It help me a lot!, thnks.