Does anyone know how I can add a timer function to this code that solves sudoku puzzles?
I've tried the Stopwatch class but I can't get it to work because I don't know exactly where to put it. I've tried several places but always get errors. The main purpose of the code works but I'd like to add a timer function to see how long the code ran for.
using System;
namespace SuDoKu
{
public class SuDoKu
{
private int[,] grid;
public SuDoKu()
{
grid = new int[9, 9];
}
static void Main(string[] args)
{
SuDoKu sdk = new SuDoKu();
int[,] grd = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
sdk.EnterToGrid(grd[i, j], new Point(i, j));
Console.WriteLine("Original Grid");
sdk.Display();
sdk.Solve(sdk.NextAvailableCell(), new Point());
Console.WriteLine("\n\n\nSolved Grid");
sdk.Display();
Console.WriteLine();
}
public void Display()
{
for(int i = 0; i < 9; i++)
{
Console.WriteLine();
for(int j = 0; j < 9; j++)
{
if(ShowFromGrid(new Point(i, j)) == 0) {
Console.Write("0 ");
}
else
{
Console.Write(ShowFromGrid(new Point(i, j)) + " ");
}
if(j == 2 || j == 5)
{
Console.Write("| ");
}
}
if(i == 2 || i == 5) {
Console.Write("\n------|-------|------ ");
}
}
}
public void EnterToGrid(int num, Point pos) {
grid[pos.X, pos.Y] = num;
}
public int ShowFromGrid(Point pos) {
return grid[pos.X, pos.Y];
}
public void Solve(Point pos, Point prevPos) {
if(pos.X < 9 && pos.Y < 9)
{
Point posPrev = new Point();
if(grid[pos.X, pos.Y] == 0)
{
for(int i = 1; i <= 9; i++)
{
if(IsThisNumberPossibleInTheGrid(i, pos))
{
grid[pos.X, pos.Y] = i;
posPrev.X = pos.X;
posPrev.Y = pos.Y;
Point posNext = NextAvailableCell();
if(!posNext.Equals(new Point()))
Solve(posNext, posPrev);
}
}
if(grid[pos.X, pos.Y] == 0)
{
if(!prevPos.Equals(new Point()))
grid[prevPos.X, prevPos.Y] = 0;
return;
}
}
}
else
{
Point posNext = NextAvailableCell();
if(!posNext.Equals(new Point()))
Solve(posNext, pos);
}
}
public Point NextAvailableCell()
{
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
if(grid[i, j] == 0)
return new Point(i, j);
return new Point();
}
public bool IsThisNumberPossibleInTheGrid(int num, Point pos) {
if(IsThisNumberPossibleInTheBlock(num, pos))
{
for(int i = 0; i < 9; i++)
{
if(grid[i, pos.Y] == num && pos.X != i)
{
return false;
}
if(grid[pos.X, i] == num && pos.Y != i)
{
return false;
}
}
return true;
}
return false;
}
public bool IsThisNumberPossibleInTheBlock(int num, Point pos)
{
Point Grid = new Point();
Grid.X = (pos.X >= 0 && pos.X <= 2) ? 0 : ((pos.X >= 3 && pos.X <= 5) ? 3 : ((pos.X >= 6 && pos.X <= 8) ? 6 : -1));
Grid.Y = (pos.Y >= 0 && pos.Y <= 2) ? 0 : ((pos.Y >= 3 && pos.Y <= 5) ? 3 : ((pos.Y >= 6 && pos.Y <= 8) ? 6 : -1));
if(!Grid.Equals(new Point()))
{
for(int i = Grid.X; i < Grid.X + 3; i++)
{
for(int j = Grid.Y; j < Grid.Y + 3; j++)
{
if(grid[i, j] == num && !pos.Equals(new Point(i, j)))
return false;
}
}
return true;
}
return false;
}
}
public class Point
{
public int X;
public int Y;
public Point()
{
this.X = -1;
this.Y = -1;
}
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public bool Equals(Point p)
{
return (this.X == p.X && this.Y == p.Y) ? true : false;
}
}
}
The Stopwatch object is often used to (as you do here), measure how long things take. One quick thing to remember here is that it will take the time for everything you do between starting and stopping it, so make sure you only put the actual code you want to time between those.
using System.Diagnostics;
//...
void StopwatchUsingMethod()
{
//A: Setup and stuff you don't want timed
var timer = new Stopwatch();
timer.Start();
//B: Run stuff you want timed
timer.Stop();
TimeSpan timeTaken = timer.Elapsed;
string foo = "Time taken: " + timeTaken.ToString(#"m\:ss\.fff");
}
Foo will here show the minutes, seconds, and milliseconds it took to complete, though will show as wrong if it takes more than 59 minutes. Further information about TimeSpan can be found here: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-timespan-format-strings
If I understand your code correctly, you want to put everything up to and including the first sdk.Display(); line in the A section and only put the call to Solve in the B section, so something like
static void Main(string[] args)
{
//...
sdk.Display();
var timer = new Stopwatch();
timer.Start();
sdk.Solve(sdk.NextAvailableCell(), new Point());
timer.Stop();
Console.WriteLine("\n\n\nSolved Grid");
//...you can use the time taken here
}
In .NET 7.0 there were some improvements in the Stopwatch class. There is a better way to use Stopwatch that will be more accurate, slightly faster, and won't use memory allocation at all!
You should use the methods Stopwatch.GetTimeStamp() & Stopwatch.GetElapsedTime(long) to make the improvements.
An example would be:
long startTime = Stopwatch.GetTimestamp();
// Do Something...
TimeSpan elapsedTime = Stopwatch.GetElapsedTime(startTime);
For more info, read the Stopwatch in .NET 7.0 documentation.
"The main purpose of the code works but I'd like to add a timer function to see how long the code ran for"
For this you can use System.Diagnostics.Stopwatch(https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.7.2).
If you want to see how long a function takes to execute, add stopWatch.Start() before and stopWatch.Stop() after the function calls. You can now see total time it took(in seconds/milliseconds etc) using stopWatch.Elapsed, according to your convenience.
Related
I'm a beginner of learning programming
Instantiate(o, new Vector3(LocateX, LocateY, 0), transform.rotation);
In this code Visual Studio 2022 keeps telling me there is an error with LocateX and LocateY...
Please help me
using Unity
error code : CS0165
FixedCode
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
public class OXScript : MonoBehaviour
{
private int clickNumber;
public GameObject o;
public int spotNumber;
// Start is called before the first frame update
void Start()
{
clickNumber= 0;
}
// Update is called once per frame
void Update()
{
}
public void SpawnO()
{
// 1, 2, 3, y = 3
// 4, 5, 6, y = 0
// 7, 8, 9, y = -3
// x=-3 x=0 x=3
float LocateX = 0;
float LocateY = 0;
int ix = 0;
for(int i=1; i<10; i++)
{
if (clickNumber == 0 && spotNumber == i)
{
// y
if(1 <= i && i <= 3 )
{
LocateY = 3;
} else if(4 <= i && i <= 6)
{
LocateY = 0;
} else if (7 <= i && i <= 9)
{
LocateY = -3;
}
//x
if (ix == (i - 1) % 3)
{
LocateX = -3;
} else if (ix + 1 == (i - 1) % 3)
{
LocateX = 0;
} else if (ix + 2 == (i - 1) % 3)
{
LocateX = 3;
}
Instantiate(o, new Vector3(LocateX, LocateY, 0), transform.rotation);
spotNumber ++;
clickNumber ++;
}
}
}
}
Problem Solved!!
I know my code is not clean at all so thank you for helping noob everyone!
Initialization is required before using local variables.
float LocateX = 0;
float LocateY = 0;
You can try using modulo arithemtics here: for
1, 2, 3 y = 3
4, 5, 6 y = 0
7, 8, 9 y = -3
x = -3 x = 0 x = 3
we can put
x = ((i - 1) % 3 - 1) * 3
y = (1 - (i - 1) / 3) * 3
And get
public void SpawnO() {
for (int i = 1; i < 10; ++i) {
if (clickNumber == 0 && spotNumber == i) {
int LocateX = ((i - 1) % 3 - 1) * 3
int LocateY = (1 - (i - 1) / 3) * 3;
Instantiate(o, new Vector3(LocateX, LocateY, 0), transform.rotation);
spotNumber += 1;
}
}
}
I have the following question:-
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
now i tried this code:-
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution
{
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
int n = 1;
Array.Sort(A);
for (int i = 1; i <= 100000; i++)
{
for (int i2 = 0; i2 <= A.Length - 1; i2++)
{
if (A[i2] == i)
{
n = A[i2] + 1;
break;
}
}
}
return n;
}
}
where my code worked well for these test data:-
A = [1, 2, 3]
A = [−1, −3]
while failed for this one:-
A = [1, 3, 6, 4, 1, 2] where it return 7 instead of 5.
any advice why my code failed on the 3rd test?
Thanks
using System.Linq;
int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();
I would use following approach that uses a HashSet<int> to check if a given integer is missing:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
A HashSet is a collection if unique values and it's very efficient in lookup items(complexity is O(1)). So you get a very readable and efficient algorithm at the cost of some memory.
Maybe you could optimize it by providing another algorithm in case the array is very large, you don't want to risk an OutOfMemoryException:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
if(A.Length > 1_000_000)
{
Array.Sort(A);
for (int i = rangeStart; i <= rangeEnd; i++)
{
int index = Array.BinarySearch(A, i);
if(index < 0) return i;
}
return null;
}
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
If you're allowed to sort the array in-place, which means modifying the input parameter value, here's a simple linear probe for the missing value (on top of the sort of course).
Here's the pseudo-code:
Sort the array
Skip all negatives and 0's at the start
Loopify the following:
Expect 1, if not found at current location return 1
Skip all 1's
Expect 2, if not found at current location return 2
Skip all 2's
Expect 3, if not found at current location return 3
Skip all 3's
... and so on for 4, 5, 6, etc. until end of array
If we get here, return currently expected value which should've been at the end
Here's the code:
public static int FirstMissingValue(int[] input)
{
Array.Sort(input);
int index = 0;
// Skip negatives
while (index < input.Length && input[index] < 1)
index++;
int expected = 1;
while (index < input.Length)
{
if (input[index] > expected)
return expected;
// Skip number and all duplicates
while (index < input.Length && input[index] == expected)
index++;
expected++;
}
return expected;
}
Test-cases:
Console.WriteLine(FirstMissingValue(new[] { 1, 3, 6, 4, 1, 2 }));
Console.WriteLine(FirstMissingValue(new[] { 1, 2, 3 }));
Console.WriteLine(FirstMissingValue(new[] { -1, -3 }));
output:
5
4
1
Your alg won't work in case input array becomes like this: [1,2-1,1,3,5]. I did this based on your alg. Give it a try:
int[] a = new int[] { -1, -2};
IEnumerable<int> uniqueItems = a.Distinct<int>().Where(x => x > 0);
if (uniqueItems.Count() == 0)
{
Console.WriteLine("result: 1");
}
else
{
Array asList = uniqueItems.ToArray();
Array.Sort(asList);
for (int i = 1; i <= 100000; i++)
{
if ((int)asList.GetValue(i - 1) != i)
{
Console.WriteLine("result: " + i);
break;
}
}
}
you can try like this.
public static int solution(int[] A)
{
int smallest = -1;
Array.Sort(A);
if(A[0] > 1)
return 1;
for(int i = 0; i < A.Length; i++)
{
if(A.Length != i+1 && A[i] + 1 != A[i + 1] && A[i+1] > 0)
{
smallest = A[i]+1;
break;
}
else if(A[i] > 0 && A.Length == i+1)
{
smallest = A[i] + 1;
}
}
return smallest > 0 ? smallest:1;
}
Here's the approach that uses O(N) partitioning followed by an O(N) search. This approach does not use any additional storage, but it DOES change the contents of the array.
This code was converted from here. Also see this article.
I've added comments to try to explain how the second stage findSmallestMissing() works. I've not commented the partitioning method, since that's just a variant of a standard partition as might be used in a QuickSort algorithm.
static class Program
{
public static void Main()
{
Console.WriteLine(FindSmallestMissing(1, 3, 6, 4, 1, 2));
Console.WriteLine(FindSmallestMissing(1, 2, 3));
Console.WriteLine(FindSmallestMissing(-1, -3));
}
public static int FindSmallestMissing(params int[] array)
{
return findSmallestMissing(array, partition(array));
}
// Places all the values > 0 before any values <= 0,
// and returns the index of the first value <= 0.
// The values are unordered.
static int partition(int[] arr)
{
void swap(int x, int y)
{
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
int pIndex = 0; // Index of pivot.
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > 0) // pivot is 0, hence "> 0"
swap(i, pIndex++);
}
return pIndex;
}
// This is the clever bit.
// We will use the +ve values in the array as flags to indicate that the number equal to that index is
// present in the array, by making the value negative if it is found in the array.
// This way we can store both the original number AND whether or not the number equal to that index is present
// in a single value.
//
// Given n numbers that are all > 0, find the smallest missing number as follows:
//
// For each array index i in (0..n):
// val = |arr[i]| - 1; // Subtract 1 so val will be between 0 and max +ve value in original array.
// if (val is in range) // If val beyond the end of the array we can ignore it
// and arr[val] is non-negative // If already negative, no need to make it negative.
// make arr[val] negative
//
// After that stage, we just need to find the first positive number in the array, which indicates that
// the number equal to that index + 1 is missing.
// n = number of values at the start of the array that are > 0
static int findSmallestMissing(int[] arr, int n)
{
for (int i = 0; i < n; i++)
{
int val = Math.Abs(arr[i]) - 1;
if (val < n && arr[val] >= 0)
arr[val] = -arr[val];
}
for (int i = 0; i < n; i++)
{
if (arr[i] > 0) // Missing number found.
return i + 1;
}
return n + 1; // No missing number found.
}
}
class Program
{
static void Main(string[] args)
{
int [] A = new int[] {1, 2, 3};
int n = 0;
bool found = false;
Array.Sort(A);
for (int i = 1; i <= 100000; i++) {
for (int x = 0; x <= A.Length - 1; x++) {
int next = (x + 1) < A.Length ? (x + 1): x;
if (A[x] > 0 && (A[next] - A[x]) > 0) {
n = A[x] + 1;
found = true;
break;
}
}
if(found) {
break;
}
}
Console.WriteLine("Smallest number: " + n);
}
}
int smallestNumber=Enumerable.Range(1,(int.Parse(A.Length.ToString())+1)).Except(A).Min();
Array.Sort(A);
for (int number = 1; number <= 100000; number++)
{
for (int num = number; i2 <= A.Length - 1; num++)
{
if (A[num] == number)
{
smallestNumber = A[num] + 1;
break;
}
}
}
return smallestNumber;
}
The easiest one :)
class Solution
{
public int solution(int[] array)
{
int[] onlyPositiveArray = array.Where(a => a > 0).OrderBy(a => a).Distinct().ToArray();
int smallestNumber = 1;
foreach (var number in onlyPositiveArray)
{
if (smallestNumber != number)
{
break;
}
smallestNumber ++;
}
if (!onlyPositiveArray.Contains(smallestNumber ))
{
return smallestNumber;
}
else
{
return smallestNumber + 1;
}
}
}
PHP Solution:
function solution($A) {
// write your code in PHP7.0
// sort array
sort($A);
// get the first
$smallest = $A[0];
// write while
while( in_array(($smallest),$A) || (($smallest) < 1 ) )
{
$smallest++;
}
return $smallest;
}
My solution, also if someone could test how performant it is?
public int solution(int[] N) {
if (N.Length == 0)
return 1;
else if (N.Length == 1)
return N[0] >= 0 ? N[0] + 1 : 1;
Array.Sort(N);
int min = Array.Find(N, IsUnderZero);
if (min ==
default)
return 1;
HashSet < int > hashSet = new HashSet < int > (N);
int max = N[N.Length - 1];
for (int i = min + 1; i <= max + 1; i++) {
if (!hashSet.Contains(i) && i > 0)
return i;
}
return max + 1;
bool IsUnderZero(int i) => i <= 0;
}
Try the below:
public static int MinIntegerGreaterThanZeroInArray(int[] A)
{
int minInt;
if (A.Length > 0)
{
Array.Sort(A);
for (minInt = 1; minInt <= A.Length; minInt++)
{
int index = Array.BinarySearch(A, minInt);
if (index < 0) return minInt;
}
return minInt;
}
//Array is empty.
throw new InvalidOperationException();
}
public static int Smallest(int[] A)
{
int maxPositiveInt = 1;
HashSet<int> NumDic = new HashSet<int>();
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(A[i]))
{
NumDic.Add(A[i]);
}
maxPositiveInt = Math.Max(A[i], maxPositiveInt);
}
//All numbers are negative
if (NumDic.Count == 0)
{
return 1;
}
int smallestinteger = 1;
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(smallestinteger))
{
return smallestinteger;
}
else
{
smallestinteger++;
}
}
return maxPositiveInt + 1;
}
static void Main(string[] args)
{
Console.WriteLine(solution(new int[]{1, 3, 6, 4, 1, 2}));
}
public static int solution(int[] A)
{
Array.Sort(A);
int smallest = A[0];
while (A.Contains(smallest+1)|| (smallest+1)<1)
{
smallest++;
}
return smallest +1;
}
//Make a method: void MogelijkePaardenSprongen(int[,] schaakbord, Positie positie) This method determines the possible positions where the Horse can jump (value 2). Of course, you do this in a smart way ( with a LOOP). Please note, there are not always 8 possibilities! The parameter position indicates where the horse is located. Test the methods (call from the Start method like the image below?
// this is the code that i have got for so far,
static void Main(string[] args)
{
Program myProgram = new Program();
myProgram.Start();
Console.ReadKey();
}
void Start()
{
int [,] schaakbord = new int [8, 8];
InitSchaakbord(schaakbord);
ToonSchaakBord(schaakbord);
}
void InitSchaakbord(int[,] schaakbord)
{
int leeg = 0;
int bezet = 1;
int mogelijkbezet = 2;
for (int i=0; i<schaakbord.GetLength(0); i++)
{
for (int j=0; j<schaakbord.GetLength(1); j++)
{
schaakbord[i, j] = leeg;
}
}
}
void ToonSchaakBord(int[,] schaakbord)
{Positie positie = new Positie();
for (int i = 0; i < schaakbord.GetLength(0); i++)
{Plaatspaard(schaakbord);
for (int j = 0; j < schaakbord.GetLength(1); j++)
{
if (schaakbord[i, j] == 0)
{
Console.Write(".");
}
else if (schaakbord[i, j] == 1)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("*");
Console.ResetColor();
}
else if (schaakbord[i, j]==2)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("*");
Console.ResetColor();
}
Console.Write(" ");
}
Console.WriteLine();
MogelijkePaardenSprongen(schaakbord, positie);
}
}
Positie Plaatspaard(int [,] schaakbord)
{Positie x = new Positie();
Random rnd = new Random();
x.waarde1 = rnd.Next(1, 8);
x.waarde2 = rnd.Next(1, 8);
for (int i = 0; i<schaakbord.GetLength(0);i++ )
{
for (int j=0; j<schaakbord.GetLength(1); j++)
{
if (x.waarde1 == i && x.waarde2 == j)
schaakbord[i, j] = 1;
}
}
return x;
}
class Positie
{
public int waarde1;
public int waarde2;
}
void MogelijkePaardenSprongen(int[,] schaakbord, Positie positie)
{
for (int i =0; i<schaakbord.GetLength(0); i++)
{
for (int j=0; j<schaakbord.GetLength(1); j++)
{
/// possible horsesteps?
/// call from void start method
if (schaakbord[i, j] == 0)
{
}
}
}
Because its assignment I don't want to give you straight whole solution. Please don't hesitate to comment if you need more help.
My suggestion is to create object
class MoveOffset
{
public int OffsetX { get; set; }
public int OffsetY { get; set; }
}
then create collection of them with possible moves
var moves = new List<MoveOffset>()
{
new MoveOffset(){OffsetX = -1, OffsetY = -2},
new MoveOffset(){OffsetX = -2, OffsetY = -1},
new MoveOffset(){OffsetX = 1, OffsetY = -2},
new MoveOffset(){OffsetX = -2, OffsetY = 1},
new MoveOffset(){OffsetX = -1, OffsetY = 2},
new MoveOffset(){OffsetX = 2, OffsetY = -1},
new MoveOffset(){OffsetX = 1, OffsetY = 2},
new MoveOffset(){OffsetX = 2, OffsetY = 1},
};
then cycle through collection and check conditions if its possible to move there from 'horse' location .
Please note that horsestep actually means that the sum of the distances
between that point and the horse should exactly be 3.
Example:
var distanceX = abs(Horse.Position.X - i);
var distanceY = abs(Horse.Position.Y - j);
bool isHorseStep = distanceX + distanceY == 3;
So you can use that assumption in your code to check if it's a horse step or not.
Here is some quickly-written code for your method.
I have not tested it but I guess you'll get the point and do adjustments if needed:
void MogelijkePaardenSprongen(int[,] schaakbord, Positie positie)
{
for (int i =0; i<schaakbord.GetLength(0); i++)
{
for (int j=0; j<schaakbord.GetLength(1); j++)
{
/// possible horsesteps?
/// call from void start method
if (schaakbord[i, j] == 0)
{
var deltaX = waarde1 - i;
var deltaY = waarde2 - j;
if (deltaX < -2 || deltaX > 2
|| deltaY < -2 || deltaY > 2 )
{
// TODO: Write logic here for out of bounds.
}
else
{
if (abs(deltaX) + abs(deltaY) == 3)
{
// TODO: Horse Step. Write your logic here.
}
}
}
}
}
}
P.S. Also for deltaY you might need to reverse the number and use something like this deltaY = j - waarde2, as the Y axis is opposite in the array.
I'm trying to use Yield so my functions wait to spawn more enemies in scene if the max amount has been reached. But now the functions skips all this while cycle in its entirety.
I have never use yield so maybe I'm understanding wrong what it does while reading the documentation.
Also maybe there is a better way to do it.
while ( i < clonesASpawnear.Length)
{
if (j <= endList)
{
if (clonesASpawnear[i] == null)
{
if (sPCurrent == sPMax)
{
sPCurrent = 0;
}
yield return new WaitUntil(() => aliveEnemies < maxAmmoutOfEnemiesOnStage);
clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
clonesASpawnear[i].SetActive(true);
clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
aliveEnemies += 1;
clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
j++;
i++;
sPCurrent++;
}
}
else
{
j = startList;
}
}
}
Edited as requested: here is the update where the function is called
void Update()
{
if (pdh.playerIsDead == false && roundOver==false)
{
playerAliveTime += Time.deltaTime;
}
if (waveNumer <= 3 )
{
timeForNextSpawn -= Time.deltaTime;
if (timeForNextSpawn <= 0 && aliveEnemies == 0)
{
nextWaveTextUI.text = nextWaveText;
int waitT = (int)waitTimeForNewWave;
StartCoroutine(delayXSeconds(waitT));
timeForNextSpawn = waitTimeForNewWave;
auxWaveThisRound--;
waveNumer++;
spawnEnemies();
}
}
else
{
if(aliveEnemies == 0 && auxWaveThisRound <= 0)
{
clearedRoundTextUI.text = clearedRoundText;
roundOver = true;
StartCoroutine(waiterReset());
}
}
accuracy = successfulProjectiles / projectileFired;
}
And the complete function where the above code is
IEnumerator spawnEnemies()
{
int percentForWave=0;
int percentForType=0;
int TotalEnemies = (int)enemySpawnsThisRound;
if (waveNumer == 1)
{
Debug.Log("Entro al wave 1");
percentForWave = 20;
percentForType = 20;
startList = 0;
}
if (waveNumer == 2)
{
Debug.Log("Entro al wave 2");
percentForWave = 70;
percentForType = 70;
startList = endList;
}
if (waveNumer == 3)
{
Debug.Log("Entro al wave 3");
percentForWave = 10;
percentForType = 10;
startList = endList;
}
int enemiesThisWave = Decimal.ToInt32(Math.Round(TotalEnemies * ((decimal)percentForWave / 100), 1));
int enemiesForType = Decimal.ToInt32(Math.Round(lenghtList * ((decimal)percentForType / 100), 1));
endList = enemiesForType + startList;
clonesASpawnear = new GameObject[enemiesThisWave];
int i = 0;
int j = startList;
while ( i < clonesASpawnear.Length)
{
if (j <= endList)
{
if (clonesASpawnear[i] == null)
{
if (sPCurrent == sPMax)
{
sPCurrent = 0;
}
yield return new WaitUntil(() => aliveEnemies < maxAmmoutOfEnemiesOnStage);
clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
clonesASpawnear[i].SetActive(true);//lo activo
clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
aliveEnemies += 1;
clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
j++;
i++;
sPCurrent++;
}
}
else
{
j = startList;
}
}
}
Do not use a while loop. Instead, use "Update()".
void Update() {
if (aliveEnemies < maxAmmoutOfEnemiesOnStage && j <= endList)
{
if (clonesASpawnear[i] == null)
{
if (sPCurrent == sPMax)
{
sPCurrent = 0;
}
clonesASpawnear[i] = Instantiate(enemyTypeList[j], spawnPoints[sPCurrent].transform.position, Quaternion.Euler(0, 0, 0)) as GameObject;
clonesASpawnear[i].SetActive(true);
clonesASpawnear[i].GetComponent<EnemyMovement_DCH>().player = Target;
aliveEnemies += 1;
clonesASpawnear[i].GetComponent<EnemyDamageHandler_DCH>().SpawnerEnemies = this;
j++;
i++;
sPCurrent++;
}
}
else
{
j = startList;
}
}
This is the idea of the Update frame. Logic in here is hit every frame. It will only continue if the number of enemies is below the max. This method MUST go into a class that extends MonoBehaviour, or else it will not be invoked. Given the intended logic, it makes sense that this would be attached to some master "game monitoring" GameObject that is managing the meta of the game along with win states etc.
EDIT (After more content):
Heres one problem "spawnEnemies();". That is an IEnumerator, but you don't use "StartCoroutine(spawnEnemies())". So the method will literally not execute. There will be no errors, but nothing in the method will occur.
I have to calculate the spectrum values of an audio.
I used aForge's FFT in Sources/Math/FourierTransform.cs and I used an example of sampling with 16 samples as used in this video to check the results with excel (I tested the results in a spreadsheet like in the video).
FFT:
public enum Direction
{
Forward = 1,
Backward = -1
};
private const int minLength = 2;
private const int maxLength = 16384;
private const int minBits = 1;
private const int maxBits = 14;
private static int[][] reversedBits = new int[maxBits][];
private static Complex[,][] complexRotation = new Complex[maxBits, 2][];
static void Main(string[] args)
{
var Data = new Complex[16];
Data[0] = new Complex(0, 0);
Data[1] = new Complex((float)0.998027, 0);
Data[2] = new Complex((float)0.125333, 0);
Data[3] = new Complex((float)-0.98229, 0);
Data[4] = new Complex((float)-0.24869, 0);
Data[5] = new Complex((float)0.951057, 0);
Data[6] = new Complex((float)0.368125, 0);
Data[7] = new Complex((float)-0.90483, 0);
Data[8] = new Complex((float)-0.48175, 0);
Data[9] = new Complex((float)0.844328, 0);
Data[10] = new Complex((float)0.587785, 0);
Data[11] = new Complex((float)-0.77051, 0);
Data[12] = new Complex((float)-0.68455, 0);
Data[13] = new Complex((float)0.684547, 0);
Data[14] = new Complex((float)0.770513, 0);
Data[15] = new Complex((float)-0.58779, 0);
FFT(Data, Direction.Forward);
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Re.ToString());
}
Console.ReadLine();
}
public static void FFT(Complex[] data, Direction direction)
{
int n = data.Length;
int m = Tools.Log2(n);
// reorder data first
ReorderData(data);
// compute FFT
int tn = 1, tm;
for (int k = 1; k <= m; k++)
{
Complex[] rotation = GetComplexRotation(k, direction);
tm = tn;
tn <<= 1;
for (int i = 0; i < tm; i++)
{
Complex t = rotation[i];
for (int even = i; even < n; even += tn)
{
int odd = even + tm;
Complex ce = data[even];
Complex co = data[odd];
double tr = co.Re * t.Re - co.Im * t.Im;
double ti = co.Re * t.Im + co.Im * t.Re;
data[even].Re += tr;
data[even].Im += ti;
data[odd].Re = ce.Re - tr;
data[odd].Im = ce.Im - ti;
}
}
}
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
}
private static int[] GetReversedBits(int numberOfBits)
{
if ((numberOfBits < minBits) || (numberOfBits > maxBits))
throw new ArgumentOutOfRangeException();
// check if the array is already calculated
if (reversedBits[numberOfBits - 1] == null)
{
int n = Tools.Pow2(numberOfBits);
int[] rBits = new int[n];
// calculate the array
for (int i = 0; i < n; i++)
{
int oldBits = i;
int newBits = 0;
for (int j = 0; j < numberOfBits; j++)
{
newBits = (newBits << 1) | (oldBits & 1);
oldBits = (oldBits >> 1);
}
rBits[i] = newBits;
}
reversedBits[numberOfBits - 1] = rBits;
}
return reversedBits[numberOfBits - 1];
}
private static Complex[] GetComplexRotation(int numberOfBits, Direction direction)
{
int directionIndex = (direction == Direction.Forward) ? 0 : 1;
// check if the array is already calculated
if (complexRotation[numberOfBits - 1, directionIndex] == null)
{
int n = 1 << (numberOfBits - 1);
double uR = 1.0;
double uI = 0.0;
double angle = System.Math.PI / n * (int)direction;
double wR = System.Math.Cos(angle);
double wI = System.Math.Sin(angle);
double t;
Complex[] rotation = new Complex[n];
for (int i = 0; i < n; i++)
{
rotation[i] = new Complex(uR, uI);
t = uR * wI + uI * wR;
uR = uR * wR - uI * wI;
uI = t;
}
complexRotation[numberOfBits - 1, directionIndex] = rotation;
}
return complexRotation[numberOfBits - 1, directionIndex];
}
// Reorder data for FFT using
private static void ReorderData(Complex[] data)
{
int len = data.Length;
// check data length
if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len)))
throw new ArgumentException("Incorrect data length.");
int[] rBits = GetReversedBits(Tools.Log2(len));
for (int i = 0; i < len; i++)
{
int s = rBits[i];
if (s > i)
{
Complex t = data[i];
data[i] = data[s];
data[s] = t;
}
}
}
These are the results after the transformation:
Output FFT results: Excel FFT results:
0,0418315622955561 0,669305
0,0533257974328085 0,716163407
0,137615673627316 0,908647001
0,114642731070279 1,673453043
0,234673940537634 7,474988602
0,0811255020953362 0,880988382
0,138088891589122 0,406276784
0,0623766891658306 0,248854492
0,0272978749126196 0,204227
0,0124250144575261 0,248854492
0,053787064184711 0,406276784
0,00783331226557493 0,880988382
0,0884368745610118 7,474988602
0,0155431246384978 1,673453043
0,0301093757152557 0,908647001
0 0,716163407
The results are not at all similar. Where is it wrong?
Is the implementation of complex (Data) wrong or is the FFT method wrong or other?
Thanks in advance!
First, the resulting FFT is a complex function in general. You're only displaying the real parts in your code but the thing you're comparing to is displaying the magnitudes, so of course they're going to be different: you're comparing apples to oranges.
When you use magnitudes and compare apples to apples, you should get this:
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Magnitude.ToString());
}
...
0.0418315622955561
0.0447602132472683
0.0567904388057513
0.104590813761862
0.46718679147454
0.0550617784710375
0.025392294285886
0.0155534081359397
0.0127641875296831
0.0155534081359397
0.025392294285886
0.0550617784710375
0.46718679147454
0.104590813761862
0.0567904388057513
0.0447602132472683
That looks a little better -- it has the same symmetry property as the Excel output and there appear to be peaks in the same locations.
It almost looks like the scale is off. If I divide each element by the corresponding element from the Excel output, I get:
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
So your results are pretty much correct, just off by a scaling factor.
You're dividing everything by n in the last step of your FFT:
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
This is conventionally done for the inverse transform, not the forward transform.
In summary, changing the output from Data[a].Re to Data[a].Magnitude and changing the condition at the end of FFT from if (direction == Direction.Forward) to if (direction == Direction.Backward), I get this output:
0.669304996728897
0.716163411956293
0.908647020892022
1.67345302018979
7.47498866359264
0.880988455536601
0.406276708574176
0.248854530175035
0.20422700047493
0.248854530175035
0.406276708574176
0.880988455536601
7.47498866359264
1.67345302018979
0.908647020892022
0.716163411956293
which matches the Excel output.