In many programming languages, assignments are legal in loops statement like this.
while(variable1 = someFunction()){
...
}
although it would be more clear code to assign variables like this I am wondering if someFunction function has a computational process in it's, it would be a better way to assign variable before loops like this
variable1 = someFunction()
while(variable1){
...
}
or no matter and compilers can detect this to do not compute it again
I tested this in Java,JavaScript and Python that are popular languages.
in every language first I have a function that sums from number 1 to 1000.
first I assign this value before the loop and see how many second take-ups to finish, then I assign this sum in a loop condition and see the result again
Java
public class Main {
public static void main(String args[]){
//assign variable before loop
long startTime= System.currentTimeMillis();
int counter = sum();
for (int i = 0; i < counter; i++) {
//some code
}
long finishTime = System.currentTimeMillis();
System.out.println("duration for assign before loop : "+(finishTime-startTime));
//assign variable in loop
startTime = System.currentTimeMillis();
for (int i = 0; i < sum(); i++) {
//some code
}
finishTime = System.currentTimeMillis();
System.out.println("duration for assign in loop : "+(finishTime-startTime));
}
public static int sum(){
int sum = 0;
for (int i = 1; i < 1000; i++) {
sum+=i;
}
return sum;
}
}
Then write this code in javascript:
function sum(){
let sum = 0;
for (let i = 1; i < 1000; i++) {
sum+=i;
}
return sum;
}
(function(){
//assign variable before loop
let startTime= Date.now();
let counter = sum();
for (let i = 0; i < counter; i++) {
//some code
}
let finishTime = Date.now();
console.log("duration for assign before loop : "+(finishTime-startTime))
//assign variable in loop
startTime = Date.now();
for (let i = 0; i < sum(); i++) {
//some code
}
finishTime = Date.now()
console.log("duration for assign in loop : "+(finishTime-startTime));
})()
and finally, I write this code in python
import time
def current_milli_time():
return int(round(time.time() * 1000))
def sum():
sum = 0
for i in xrange(1,1000):
sum += i
return sum
if __name__=="__main__":
#assign before loop
startTime = current_milli_time()
counter = sum()
for i in xrange(1,counter):
pass
finishTime = current_milli_time()
print("duration for assign before loop : "+str(finishTime-startTime))
#assign in loop
startTime = current_milli_time()
for i in xrange(1,sum()):
pass
finishTime = current_milli_time()
print("duration for assign in loop : "+str(finishTime-startTime))
the result was interesting.I got this result in every language
Java :
duration for assign before loop : 2
duration for assign in loop : 326
JavaScript :
duration for assign before loop : 4
duration for assign in loop : 1846
but in python I got
duration for assign before the loop : 66
duration for assign in a loop : 67
as we can see in Java and JavaScript we absolutely should not use assign variable in loops if it results is the same during loop but in python, we got almost very close duration.
Conclusion
as a conclusion, I think it's no matter what programming language we use but it's better to don't assign variables in loops if it results remain the same during the loop
Related
I have made a very simple algorithm that picks a set of numToPick random numbers from the range 0 to batchMax, without replacement. Then it places each selected number in an array called numsPicked. For some reason I cannot explain, it isn't working on DartPad.
import 'dart:math';
void main() {
print(randNoReplace(2, 9));
}
List<int> randNoReplace(int numToPick, int batchMax) {
List<int> numsPicked = List(numToPick);
List<int> tmpArray = List(batchMax);
//this for loop creates the tmpArray from 0 to batchMax.
for (int i = 0; i <= batchMax; i++) {
tmpArray[i] = i;
}
//this for loop randomly scrambles said tmpArray.
for (int i = 0; i <= batchMax; i++) {
int randIndex = Random().nextInt(batchMax);
int tmp = tmpArray[i];
tmpArray[i] = tmpArray[randIndex];
tmpArray[randIndex] = tmp;
}
//finally, this for loop adds the first numToPick entries of the scrambled tmpArray and adds them to numsPicked.
for (int i = 0; i < numToPick; i++) {
numsPicked[i] = tmpArray[i];
}
return numsPicked;
}
So, for example, with 2 and 9 respectively, this algorithm should theoretically give me 2 random non-duplicate numbers in the range [0, 9].
I think the main issue in your code is that your first two for-loops are going from 0 to
batchMax including batchMax. This is a problem since you are using batchMax to specify the size of your tmpArray. Since the index of a List starts at 0, we cannot ask for the batchMax-element but at most batchMax - 1.
So you code should properly be (or `tmpArray should be one element bigger):
import 'dart:math';
void main() {
print(randNoReplace(2, 9));
}
List<int> randNoReplace(int numToPick, int batchMax) {
List<int> numsPicked = List(numToPick);
List<int> tmpArray = List(batchMax);
//this for loop creates the tmpArray from 0 to batchMax.
for (int i = 0; i < batchMax; i++) {
tmpArray[i] = i;
}
//this for loop randomly scrambles said tmpArray.
for (int i = 0; i < batchMax; i++) {
int randIndex = Random().nextInt(batchMax);
int tmp = tmpArray[i];
tmpArray[i] = tmpArray[randIndex];
tmpArray[randIndex] = tmp;
}
//finally, this for loop adds the first numToPick entries of the scrambled tmpArray and adds them to numsPicked.
for (int i = 0; i < numToPick; i++) {
numsPicked[i] = tmpArray[i];
}
return numsPicked;
}
Some other minor comments:
You should properly not initialize a new Random() object each time you need a random number. Instead, you should create one instance and reuse it.
Your code are not making much use of the Dart SDK. In fact, your code could properly be simplified into:
void main() {
print(randNoReplace(2, 9));
}
List<int> randNoReplace(int numToPick, int batchMax) =>
(List.generate(batchMax, (index) => index)..shuffle())
.sublist(0, numToPick);
I want to change the iteration statement and condition within for loop as below.
for (int i=0; i<n; i++)
Here n is value which is entered by user. According to "n" value iteration statement should be change.
if n=10 --> i will increase by 1
if n = 100 --> i will increase by 10
But there is no limitation for n value. Is there is way to achieve this?
You can do it with something like this:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//get n value
int n = sc.nextInt();
for (int i = 0; i < n; i += (int) (0.1 * n)) {
//loop code
}
}
}
For example let's say the user enters n = 10000
The first loop i = 0 so the increment will be:
i = 0 + (int) (0.1 * 10000)
i = 1000
The second loop i = 1000 so the increment will be:
i = 1000 + (int) (0.1 * 10000)
i = 2000
and so on...
The code will work as long as the user enters n value that's divided by 10 with 0 remainder.
Code below, it should be O(n). There are two loops, I know this. But that doesn't necessarily mean it's O(n^2). The function loops won't run more than n + 1 times (at least as far as I can tell!). That should be O(n). Am I wrong? Can someone help me out? Thanks!
EDIT: The program puts odd integers at the front and even integers at the back of an array!!!
public class Main {
public static void main(String[] args) {
int[] array = new int[]{5, 4, 3, 2, 1, 0};
organizeArray(array);
for (int j = 0; j < array.length; j++) {
System.out.println(array[j]);
}
}
public static void organizeArray(int[] array) {
int end = array.length - 1;
for (int i = 0; i < array.length; i++) {
int temp = 0;
while (true) {
if (i == end)
break;
if (array[i] % 2 == 0) {
temp = array[i];
array[i] = array[end];
array[end] = temp;
end = end - 1;
}
if (array[i] % 2 != 0)
break;
}
if (i == end)
break;
}
}
}
As the other question was a duplicate of this one, let me post my answer here.
The code is O(n) as you either increase i or reduce end. In any case, you decrease the rest of work (n) by one.
For your upcoming homework: You can test your thoughts about big-O easily just by trying out. Most of the time the number of tests doesn't need to be very big. It will not be a proof but it gives you a good hint if your thoughts are correct or not.
Here's is my code for your problem with 100 tests. It produces 100 pairs of numbers: The length of the array and the number of loops. You take this list and bring it to a graph.
public class Main {
public static void main(String[] args) {
Main main = new Main();
Random random = new Random();
for (int i = 0; i < 100; i++) {
int[] array = new int[random.nextInt(10000 - 10) + 10]; // between 10 and 9999 numbers long
for (int j = 0; j < array.length; j++) array[j] = random.nextInt();
main.organize(array);
}
}
private int[] organize(int[] array) {
long loops = 0;
int end = array.length-1;
// I've shorten your code here. This does the same with less breaks
for (int i = 0; i < end; i++) {
while(i < end && array[i] % 2 == 0) {
swap(array, i, end--);
loops++;
}
}
System.out.printf("%d\t%d\n", array.length, loops);
return array;
}
private void swap(int[] array, int a, int b) {
int t = array[a];
array[a] = array[b];
array[b] = t;
}
}
And the graph looks like a straight line. So your proof should result in O(n), right?
Interesting code. The inner for loop will break when the i'th element is odd. If its not odd then it will swap elements from the end until an odd one is found. Since end is decremented upon each swap and the program completes when i reaches end, it follows that i or end can get incremented/decremented, respectively at most O(n) times. Because of this, and because all other operations in the loops are O(1), the program indeed runs in time O(n) despite there being nested loops.
I am preparing for the exam, where I came to this question:
What is the total running time of the following code (N is an int variable)
Z z = new Z(N);
for (int i = 0; i < N; i++) z.insert("Bob", i);
Class Z:
public class Z
{
String[] names;
Integer[] numbers;
int N = 0;
public Z(int cap)
{
names = new String[cap];
numbers = new Integer[cap];
}
public Integer find(String S)
{
for (int i = 0; i < N; i++)
{
if (names[i].equals(S)) return numbers[i];
}
return null;
}
public void insert(String S, Integer M)
{
for (int i = 0; i < N; i++)
{
if (names[i].equals(S)) numbers[i] = M;
}
names[N] = S;
numbers[N] = M;
N++;
}
}
I think the answer for this question is O(n^2). The first for loop takes O(n) times, and the method insert takes O(n) times (notice: n++ on every insert call), which total gives O(n^2)
First note that the N variable in the main part is not the same as the N referenced within the object instance.
After the z object is created, its private N member is equal to 0 and only increases with every call to insert.
So the number of times the loop in the insert method iterates is equal to the number of previous calls made to the insert method.
So the total number iterations made in the insert method (taking all the N calls together) is:
Σi=0..N-1 (i)
This is equal to:
½N(N-1)
which is ½N² - ½N and thus O(n²)
I have declared a two dimensional array "S" in a class as follows:
public class TestClass {
private static final List<List<Long>> S = new List<List<Long>>{};
Public TestClass {
}
public void setKey(string key, string keylength) {
integer i, j
for ( i = 0; i < 4; ++i ){
for ( j = 0; j < 256; ++j ){
S[i][j] = 0;
}
}
}
}
Im getting a List index out of bounds: 0 at this line:
S[i][j] = 0;
It seems that its not calling the List correctly,
Can someone please tell me what's wrong?
Thanks
I don't have any experience in apex-code, but I'd guess that you haven't initialised the List elsewhere in the code, or at least not initialised the inner List.
Putting this in context with a well known language such as C# or Java, the initialisation would look something like this:
// ** NOTE: Pseudo-code **
// Loop over the outer List first
for ( i = 0; i < 4; ++i ){
// Initialise each List index as a new List, storing 256 integers.
S[i] = new List<long>(new int[256]);
// Loop over the newly initialised inner List, setting the int values.
for ( j = 0; j < 256; ++j ){
S[i][j] = 0;
}
}
}