I am using an iterative method to delete a folder and all its children. So if Folder A gets deleted then all its children i.e b,c,d,e,f get deleted also.
What I have works as I have tested it quite a bit, but I'm not sure if it should be done more efficiently using recursion? Should I use it, in the long run my database could be quite large meaning performance will be an issue in the future.
int thisId = params.int('thisId')
def datafile = Datafile.get(thisId)
int parentId = datafile.parent_id
boolean continueIteration = true
List<Datafile> itemsToBeDeleted = new ArrayList<Datafile>();
Set<Datafile> folderfileList;
Set<Datafile> tempfolderfileList = new HashSet<Datafile>();
Set<Datafile> temp;
List<Datafile> initialDatafileList = Datafile.findAllByParent_id(thisId)
itemsToBeDeleted.add(Datafile.findById(thisId))
for(int i=0; i<initialDatafileList.size(); i++){
continueIteration = true;
System.out.println("1st "+initialDatafileList.get(i).id)
folderfileList = Datafile.findAllByParent_id(initialDatafileList.get(i).id)
itemsToBeDeleted.add(Datafile.findById(initialDatafileList.get(i).id))
while(continueIteration) {
if(folderfileList.size() >=1){
for(Datafile df: folderfileList){
// System.out.println("2nd "+df.id)
temp = Datafile.findAllByParent_id(df.id)
for(Datafile z: temp ){
System.out.println("temp "+z.id)
}
if(temp.size()>=1){
tempfolderfileList.addAll(temp)
}
temp.clear()
}
}
else{
continueIteration = false
}
for(Datafile y: folderfileList ){
// System.out.println("see if they are here "+y.id)
}
itemsToBeDeleted.addAll(folderfileList)
folderfileList.clear();
folderfileList.addAll(tempfolderfileList); //changed from =
tempfolderfileList.clear();
}
}
for(Datafile y: itemsToBeDeleted ){
System.out.println("deleted "+y.id)
}
itemsToBeDeleted*.delete(flush:true)
Related
I'm trying to implement my own neat implementation and I can't get myself to understand how speciation works
I tried my best to follow the pesudocode I found in this paper (start of page 13)
but I'm think I'm doing it really wrong but I don't understand the right way to do it, here is my code
the sepciate function that splits the population into species:
function speciate(population, species=[]) {
let newSpecies = [...species];
for(const net of population) {
let placed = false;
for(const s of newSpecies) {
for(const member of s) {
if(sh(net, member)) {
s.push(net);
placed = true;
break;
}
}
if(placed) break;
}
if(!placed) {
newSpecies.push([net]);
}
}
return newSpecies;
}
the repopulation function that generates a new population using the number of offsprings:
function repopulate(popCount, species) {
let globalAvg = 0;
species.forEach(s => {
globalAvg += s.reduce((P, net) => P + net.genome.fitness, 0) / s.length;
});
let newPop = [];
for(const s of species) {
let N = popCount;
let sAvg = s.reduce((P, net) => P + net.genome.fitness, 0) / s.length;
let offspringCount = (sAvg / globalAvg) * N;
for(let i = 0; i < offspringCount; i++) {
let parent1 = wheelSelect(s);
let parent2 = wheelSelect(s);
let child = parent1.genome.crossover(parent2.genome);
child.mutateAddNeuron(0.01);
child.mutateAddConnection(0.01);
child.mutateWeight(0.01);
child.mutateEnabledToggle(0.01);
child.layerNeurons();
let net = new NeuralNetwork();
net.wireUsingGenome(child);
newPop.push(net);
}
}
return newPop;
}
the problem I'm facing is that the population number seems to change every new generation sometimes it goes up and sometimes down, so I'm gussing I'm calculating the offspring count wrong or my speciation isn't working correctly but I can't figure it out
any help is appreciated!
I have to Lists:
list1 = [1,2,3,3,3,4,4,5];
list2 = [3,4,5];
I want to get the intersection:
A = [1,2,3,3,4,5]
The condition is: ALL_ELEMENTS_OFF_A+ ALL_ELEMENTS_OFF_LIST2 = ALL_ELLEMENTS_OF_LIST1 ; list1>list2
Thanks to everyone who can help.
I found a way to get the intersection of: List1∩List2
while(list2.isNotEmpty){
for (int i = 0; i < list1.length;) {
if (list2.last== list1[i]) {
list2.removeLast();
list1.removeAt(i);
break;
} else {
i++;
}
}
}
I have a binary image and a color image of the same size. I need to iterate each blob (white pixel blocks) of the binary image and use it as a mask and find the mean color of this blob region from the color image.
I have tried:
HierarchyIndex[] hierarchy;
Point[][] contours;
binaryImage.FindContours(out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone);
using (Mat mask = Mat.Zeros(matColor.Size(), MatType.CV_8UC1))
foreach (var bl in contours)
if (Cv2.ContourArea(bl) > 5)
{
mask.DrawContour(bl, Scalar.White, -1);
Rect rect = Cv2.BoundingRect(bl);
Scalar mean = Cv2.Mean(colorImage[rect], mask[rect]);
mask.DrawContour(bl, Scalar.Black, -1);
}
which works for the blobs not having holes. However in my case I have many blob regions having huge holes that affects the mean calculation.
I couldn't figure it out how to solve it using the hierarchy info; or with another approach.
(My code is for OpenCVSharp but answer in any other wrapper or language is wellcome.)
Edit: I've added an example image. The traffic signs part is the problem.
Actually I think I have solved this problem with this method:
using PLine = List<Point>;
using Shape = List<List<Point>>;
internal static IEnumerable<Tuple<PLine, Shape>> FindContoursWithHoles(this Mat mat)
{
Point[][] contours;
HierarchyIndex[] hierarchy;
mat.FindContours(out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
Dictionary<int, bool> dic = new Dictionary<int, bool>();
for (int i = 0; i < contours.Length; i++)
if (hierarchy[i].Parent < 0)
dic[i] = true;
bool ok = false;
while (!ok)
{
ok = true;
for (int i = 0; i < contours.Length; i++)
if (dic.ContainsKey(i))
{
bool isParent = dic[i];
var hi = hierarchy[i];
if (hi.Parent >= 0) dic[hi.Parent] = (!isParent);
if (hi.Child >= 0) dic[hi.Child] = (!isParent);
while (hi.Next >= 0)
{
dic[hi.Next] = isParent;
hi = hierarchy[hi.Next];
if (hi.Parent >= 0) dic[hi.Parent] = (!isParent);
if (hi.Child >= 0) dic[hi.Child] = (!isParent);
}
hi = hierarchy[i];
while (hi.Previous >= 0)
{
dic[hi.Previous] = isParent;
hi = hierarchy[hi.Previous];
if (hi.Parent >= 0) dic[hi.Parent] = (!isParent);
if (hi.Child >= 0) dic[hi.Child] = (!isParent);
}
}
else
ok = false;
}
foreach (int i in dic.Keys.Where(a => dic[a]))
{
PLine pl = contours[i].ToList();
Shape childs = new Shape();
var hiParent = hierarchy[i];
if (hiParent.Child >= 0)
{
childs.Add(contours[hiParent.Child].ToList());
var hi = hierarchy[hiParent.Child];
while (hi.Next >= 0)
{
childs.Add(contours[hi.Next].ToList());
hi = hierarchy[hi.Next];
}
hi = hierarchy[hiParent.Child];
while (hi.Previous >= 0)
{
childs.Add(contours[hi.Previous].ToList());
hi = hierarchy[hi.Previous];
}
}
yield return Tuple.Create(pl, childs);
}
}
By drawing the holes as black, we can use each blob as a single mask:
var blobContours = blobs.FindContoursWithHoles().ToList();
using (Mat mask = Mat.Zeros(mat0.Size(), MatType.CV_8UC1))
for (int i = 0; i < blobContours.Count; i++)
{
var tu = blobContours[i];
var bl = tu.Item1;
if (Cv2.ContourArea(bl) > 100)
{
mask.DrawContour(bl, Scalar.White, -1);
foreach (var child in tu.Item2)
mask.DrawContour(child, Scalar.Black, -1);
Rect rect = Cv2.BoundingRect(bl);
Scalar mean = Cv2.Mean(mat0[rect], mask[rect]);
}
}
I think there should be an easier way.
And yet there is another problem. In some cases, an individual red part of the sign (which is a seperate white blob) does not found as a parent outside circle and a child inside circle, but a large parent contour outside with two circles as children (ie. hole inside another hole, makes a seperate blob which is not found as a parent). Yes it is hierarchically correct but does not help me. I hope I could make my self clear, sorry for my English.
#Miki thank you very much. I was able to achieve what I want using ConnectedComponents. Its simple and fast:
var cc = Cv2.ConnectedComponentsEx(binaryImage, PixelConnectivity.Connectivity8);
foreach (var bl in cc.Blobs)
using (Mat mask = new Mat())
{
cc.FilterByBlob(binaryImage, mask, bl);
Rect rect = bl.Rect;
Scalar mean = Cv2.Mean(colorImage[rect], mask[rect]);
}
Hi I keep getting the error: expecting identifier before greater than.
on line 13.
Any help would be nice please and Thank you.
fly = function () {
this.animate = function() {
// Capture mouse positions and distance from mouse
this.targetX = _root._xmouse;
this.targetY = _root._ymouse;
this.distX = this.targetX-this.meX+this.flockX;
this.distY = this.targetY-this.meY+this.flockY;
//
if ((this.targetX == this.oldTargetX) && Math.random()>0.9) {
// add small scale random darting if mouse is still
this.flockX = (Math.random()*100)-50;
this.flockY = (Math.random()*100)-50;
} else if ((this.targetX<>this.oldTargetX) && Math.random()>0.8) {
// add large scale random darting if mouse is moving
this.flockX = (Math.random()*400)-200;
this.flockY = (Math.random()*400)-200;
}
// Apply inertia equation
this.meX = Math.round(this.meX+(this.distX)/20);
this.meY = Math.round(this.meY+(this.distY)/20);
// perform animation
this._x = this.meX;
this._y = this.meY;
// remember the current mouse pos so we can tell if
// it has moved next time around
this.oldTargetX = this.targetX;
};
this.initialize = function() {
this.targetX = 0;
this.targetY = 0;
this.distX = 0;
this.distY = 0;
this.meX = this._x;
this.meY = this._y;
this.oldTargetX = 0;
this.flockX = (Math.random()*200)-100;
this.flockY = (Math.random()*200)-100;
};
// set up onEnterFrame script to animate _parent...
this.initialize();
this.onEnterFrame = this.animate;
};
//
//
var i:Number = 0;
var bugClip:MovieClip;
for (i=0; i<30; i++) {
bugClip = this.attachMovie("bug", "bug"+i, i);
fly.apply(bugClip);
}
I don't know about Actionscript, but by looking at your code I would recomend doing like this:
randomValue = Math.random()
if ((this.targetX == this.oldTargetX) && randomValue>0.9) {
The <> operator for not equals has been deprecated since Flash Player 5 Doc reference here
You should use != for the same functionality.
Although i tested this on Flash Player 10.2 and it will still compile and run with no errors. I guess you are compiling to a later version.
How can I compute a MD5 or SHA1 hash of text in a specific cell and set it to another cell in Google Spreadsheet?
Is there a formula like =ComputeMD5(A1) or =ComputeSHA1(A1)?
Or is it possible to write custom formula for this? How?
Open Tools > Script Editor then paste the following code:
function MD5 (input) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
var txtHash = '';
for (i = 0; i < rawHash.length; i++) {
var hashVal = rawHash[i];
if (hashVal < 0) {
hashVal += 256;
}
if (hashVal.toString(16).length == 1) {
txtHash += '0';
}
txtHash += hashVal.toString(16);
}
return txtHash;
}
Save the script after that and then use the MD5() function in your spreadsheet while referencing a cell.
This script is based on Utilities.computeDigest() function.
Thanks to gabhubert for the code.
This is the SHA1 version of that code (very simple change)
function GetSHA1(input) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_1, input);
var txtHash = '';
for (j = 0; j <rawHash.length; j++) {
var hashVal = rawHash[j];
if (hashVal < 0)
hashVal += 256;
if (hashVal.toString(16).length == 1)
txtHash += "0";
txtHash += hashVal.toString(16);
}
return txtHash;
}
Ok, got it,
Need to create custom function as explained in
http://code.google.com/googleapps/appsscript/articles/custom_function.html
And then use the apis as explained in
http://code.google.com/googleapps/appsscript/service_utilities.html
I need to handtype the complete function name so that I can see the result in the cell.
Following is the sample of the code that gave base 64 encoded hash of the text
function getBase64EncodedMD5(text)
{
return Utilities.base64Encode( Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, text));
}
The difference between this solution and the others is:
It fixes an issue some of the above solution have with offsetting the output of Utilities.computeDigest (it offsets by 128 instead of 256)
It fixes an issue that causes some other solutions to produce the same hash for different inputs by calling JSON.stringify() on input before passing it to Utilities.computeDigest()
function MD5(input) {
var result = "";
var byteArray = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, JSON.stringify(input));
for (i=0; i < byteArray.length; i++) {
result += (byteArray[i] + 128).toString(16) + "-";
}
result = result.substring(result, result.length - 1); // remove trailing dash
return result;
}
to get hashes for a range of cells, add this next to gabhubert's function:
function RangeGetMD5Hash(input) {
if (input.map) { // Test whether input is an array.
return input.map(GetMD5Hash); // Recurse over array if so.
} else {
return GetMD5Hash(input)
}
}
and use it in cell this way:
=RangeGetMD5Hash(A5:X25)
It returns range of same dimensions as source one, values will spread down and right from cell with formulae.
It's universal single-value-function to range-func conversion method (ref), and it's way faster than separate formuleas for each cell; in this form, it also works for single cell, so maybe it's worth to rewrite source function this way.
Based on #gabhubert but using array operations to get the hexadecimal representation
function sha(str){
return Utilities
.computeDigest(Utilities.DigestAlgorithm.SHA_1, str) // string to digested array of integers
.map(function(val) {return val<0? val+256 : val}) // correct the offset
.map(function(val) {return ("00" + val.toString(16)).slice(-2)}) // add padding and enconde
.join(''); // join in a single string
}
Using #gabhubert answer, you could do this, if you want to get the results from a whole row. From the script editor.
function GetMD5Hash(value) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, value);
var txtHash = '';
for (j = 0; j <rawHash.length; j++) {
var hashVal = rawHash[j];
if (hashVal < 0)
hashVal += 256;
if (hashVal.toString(16).length == 1)
txtHash += "0";
txtHash += hashVal.toString(16);
}
return txtHash;
}
function straightToText() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var r = 1;
var n_rows = 9999;
var n_cols = 1;
var column = 1;
var sheet = ss[0].getRange(r, column, n_rows, ncols).getValues(); // get first sheet, a1:a9999
var results = [];
for (var i = 0; i < sheet.length; i++) {
var hashmd5= GetMD5Hash(sheet[i][0]);
results.push(hashmd5);
}
var dest_col = 3;
for (var j = 0; j < results.length; j++) {
var row = j+1;
ss[0].getRange(row, dest_col).setValue(results[j]); // write output to c1:c9999 as text
}
}
And then, from the Run menu, just run the function straightToText() so you can get your result, and elude the too many calls to a function error.
I was looking for an option that would provide a shorter result. What do you think about this? It only returns 4 characters. The unfortunate part is that it uses i's and o's which can be confused for L's and 0's respectively; with the right font and in caps it wouldn't matter much.
function getShortMD5Hash(input) {
var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
var txtHash = '';
for (j = 0; j < 16; j += 8) {
hashVal = (rawHash[j] + rawHash[j+1] + rawHash[j+2] + rawHash[j+3]) ^ (rawHash[j+4] + rawHash[j+5] + rawHash[j+6] + rawHash[j+7])
if (hashVal < 0)
hashVal += 1024;
if (hashVal.toString(36).length == 1)
txtHash += "0";
txtHash += hashVal.toString(36);
}
return txtHash.toUpperCase();
}
I needed to get a hash across a range of cells, so I run it like this:
function RangeSHA256(input)
{
return Array.isArray(input) ?
input.map(row => row.map(cell => SHA256(cell))) :
SHA256(input);
}