Reduce runtime for manipulating string multiple times using Hashmap / other methods

Multi tool use
The problem statement is that we have a string and we want to rotate each character to its next character i.e a
to b
, b
to c
and z
to a
. Also, the conversion is based on the number x ( x is <= size of string). The number represents the length of the characters to be converted. Let's say the number is 3 and string is stack
which means only first 3 characters need to be converted, so output will be tubck
. if the number is 5 then the output will be tubdl
.
I am running the solution for 100000000
times and generating the variable number
randomly. I have solved this problem using 3 approaches mentioned below:
- Convert from character to integer, then increment the integer by 1, then convert the integer back to character.
- Using the hashmap to get the updated character value in O(1) time.
- Using C, but the approach followed is same as of step # 1
The runtime of the hashmap technique (approach 2) is coming to be more. I don't know why?
Approach #1 is
public static void main(String args) {
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(26) + 1; j++) {
if (stringCharArray[j] == 'z') {
stringCharArray[j] = 'a';
} else {
stringCharArray[j] = (char) (((int) (stringCharArray[j])) + 1);
}
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach # 2 using hashmap is
public static void main(String args) {
HashMap hashMap = new HashMap();
hashMap.put('a', 'b');
hashMap.put('b', 'c');
hashMap.put('c', 'd');
hashMap.put('d', 'e');
hashMap.put('e', 'f');
hashMap.put('f', 'g');
hashMap.put('g', 'h');
hashMap.put('h', 'i');
hashMap.put('i', 'j');
hashMap.put('j', 'k');
hashMap.put('k', 'l');
hashMap.put('l', 'm');
hashMap.put('m', 'n');
hashMap.put('n', 'o');
hashMap.put('o', 'p');
hashMap.put('p', 'q');
hashMap.put('q', 'r');
hashMap.put('r', 's');
hashMap.put('s', 't');
hashMap.put('t', 'u');
hashMap.put('u', 'v');
hashMap.put('v', 'w');
hashMap.put('w', 'x');
hashMap.put('x', 'y');
hashMap.put('y', 'z');
hashMap.put('z', 'a');
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (Integer j = 0; j < random.nextInt(26) + 1; j++) {
stringCharArray[j] = (char) hashMap.get(stringCharArray[j]);
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach #3
#include <stdio.h>
#include <time.h>
#include <zconf.h>
#include <stdlib.h>
int main() {
long start = clock();
char name = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < rand() % 25; j++) {
if (name[j] == 'z') {
name[j] = 'a';
} else {
name[j] = (char) (((int) (name[j])) + 1);
}
}
}
}
long stop = clock();
printf("time taken = %ld sec n",( stop-start)/1000);
}
The runtime of approach 1 is ~ 8150 m, approach 2 is ~ 9700 ms and approach 3 is ~ 5400 ms. I am using MacBook Pro 2.3 GHz Intel Core i5 with 8 GB 2133 MHz LPDDR3.
How do I reduce this runtime, I used stream.parallelize()
in java for apprach#2 to make the changes but the runtime was increasing. What am I doing wrong?
The goal is to get the runtime less than approach #3. Is there a way in C to parallelize this and solve in lesser time using pthreads?
java c multithreading
|
show 3 more comments
The problem statement is that we have a string and we want to rotate each character to its next character i.e a
to b
, b
to c
and z
to a
. Also, the conversion is based on the number x ( x is <= size of string). The number represents the length of the characters to be converted. Let's say the number is 3 and string is stack
which means only first 3 characters need to be converted, so output will be tubck
. if the number is 5 then the output will be tubdl
.
I am running the solution for 100000000
times and generating the variable number
randomly. I have solved this problem using 3 approaches mentioned below:
- Convert from character to integer, then increment the integer by 1, then convert the integer back to character.
- Using the hashmap to get the updated character value in O(1) time.
- Using C, but the approach followed is same as of step # 1
The runtime of the hashmap technique (approach 2) is coming to be more. I don't know why?
Approach #1 is
public static void main(String args) {
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(26) + 1; j++) {
if (stringCharArray[j] == 'z') {
stringCharArray[j] = 'a';
} else {
stringCharArray[j] = (char) (((int) (stringCharArray[j])) + 1);
}
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach # 2 using hashmap is
public static void main(String args) {
HashMap hashMap = new HashMap();
hashMap.put('a', 'b');
hashMap.put('b', 'c');
hashMap.put('c', 'd');
hashMap.put('d', 'e');
hashMap.put('e', 'f');
hashMap.put('f', 'g');
hashMap.put('g', 'h');
hashMap.put('h', 'i');
hashMap.put('i', 'j');
hashMap.put('j', 'k');
hashMap.put('k', 'l');
hashMap.put('l', 'm');
hashMap.put('m', 'n');
hashMap.put('n', 'o');
hashMap.put('o', 'p');
hashMap.put('p', 'q');
hashMap.put('q', 'r');
hashMap.put('r', 's');
hashMap.put('s', 't');
hashMap.put('t', 'u');
hashMap.put('u', 'v');
hashMap.put('v', 'w');
hashMap.put('w', 'x');
hashMap.put('x', 'y');
hashMap.put('y', 'z');
hashMap.put('z', 'a');
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (Integer j = 0; j < random.nextInt(26) + 1; j++) {
stringCharArray[j] = (char) hashMap.get(stringCharArray[j]);
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach #3
#include <stdio.h>
#include <time.h>
#include <zconf.h>
#include <stdlib.h>
int main() {
long start = clock();
char name = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < rand() % 25; j++) {
if (name[j] == 'z') {
name[j] = 'a';
} else {
name[j] = (char) (((int) (name[j])) + 1);
}
}
}
}
long stop = clock();
printf("time taken = %ld sec n",( stop-start)/1000);
}
The runtime of approach 1 is ~ 8150 m, approach 2 is ~ 9700 ms and approach 3 is ~ 5400 ms. I am using MacBook Pro 2.3 GHz Intel Core i5 with 8 GB 2133 MHz LPDDR3.
How do I reduce this runtime, I used stream.parallelize()
in java for apprach#2 to make the changes but the runtime was increasing. What am I doing wrong?
The goal is to get the runtime less than approach #3. Is there a way in C to parallelize this and solve in lesser time using pthreads?
java c multithreading
1
Did you check how much time the programme spent in random functions ? Note also that all approaches are O(1)
– Damien
Jan 3 at 8:38
4
A better approach than theHashMap
approach (which necessarily requires boxing) is to populate an array (or even aString
):"bcde...xyza".charAt(name[0] - 'a')
.
– Andy Turner
Jan 3 at 8:43
1
for (int j = 0; j < random.nextInt(26) + 1; j++)
will callnextint
upon each iteation. I don't think you want that, so have a line before the for loop, e.g.int n=random.nextInt(26)+1;
and thenfor (int j = 0; j < n; j++)
This also optimizes the code because it eliminates unnecessary function calls.
– Paul Ogilvie
Jan 3 at 9:09
1
Notice thanfor (int j = 0; j < rand() % 25; j++)
would callrand()
at each iteration, you probably want:const int end = rand() % 25; for (int j = 0; j != end; j++)
.
– Jarod42
Jan 3 at 9:10
1
Instead of usingstringCharArray[j]
, use a pointer variable. This optimizes the code by eliminating indexing instructions.
– Paul Ogilvie
Jan 3 at 9:12
|
show 3 more comments
The problem statement is that we have a string and we want to rotate each character to its next character i.e a
to b
, b
to c
and z
to a
. Also, the conversion is based on the number x ( x is <= size of string). The number represents the length of the characters to be converted. Let's say the number is 3 and string is stack
which means only first 3 characters need to be converted, so output will be tubck
. if the number is 5 then the output will be tubdl
.
I am running the solution for 100000000
times and generating the variable number
randomly. I have solved this problem using 3 approaches mentioned below:
- Convert from character to integer, then increment the integer by 1, then convert the integer back to character.
- Using the hashmap to get the updated character value in O(1) time.
- Using C, but the approach followed is same as of step # 1
The runtime of the hashmap technique (approach 2) is coming to be more. I don't know why?
Approach #1 is
public static void main(String args) {
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(26) + 1; j++) {
if (stringCharArray[j] == 'z') {
stringCharArray[j] = 'a';
} else {
stringCharArray[j] = (char) (((int) (stringCharArray[j])) + 1);
}
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach # 2 using hashmap is
public static void main(String args) {
HashMap hashMap = new HashMap();
hashMap.put('a', 'b');
hashMap.put('b', 'c');
hashMap.put('c', 'd');
hashMap.put('d', 'e');
hashMap.put('e', 'f');
hashMap.put('f', 'g');
hashMap.put('g', 'h');
hashMap.put('h', 'i');
hashMap.put('i', 'j');
hashMap.put('j', 'k');
hashMap.put('k', 'l');
hashMap.put('l', 'm');
hashMap.put('m', 'n');
hashMap.put('n', 'o');
hashMap.put('o', 'p');
hashMap.put('p', 'q');
hashMap.put('q', 'r');
hashMap.put('r', 's');
hashMap.put('s', 't');
hashMap.put('t', 'u');
hashMap.put('u', 'v');
hashMap.put('v', 'w');
hashMap.put('w', 'x');
hashMap.put('x', 'y');
hashMap.put('y', 'z');
hashMap.put('z', 'a');
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (Integer j = 0; j < random.nextInt(26) + 1; j++) {
stringCharArray[j] = (char) hashMap.get(stringCharArray[j]);
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach #3
#include <stdio.h>
#include <time.h>
#include <zconf.h>
#include <stdlib.h>
int main() {
long start = clock();
char name = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < rand() % 25; j++) {
if (name[j] == 'z') {
name[j] = 'a';
} else {
name[j] = (char) (((int) (name[j])) + 1);
}
}
}
}
long stop = clock();
printf("time taken = %ld sec n",( stop-start)/1000);
}
The runtime of approach 1 is ~ 8150 m, approach 2 is ~ 9700 ms and approach 3 is ~ 5400 ms. I am using MacBook Pro 2.3 GHz Intel Core i5 with 8 GB 2133 MHz LPDDR3.
How do I reduce this runtime, I used stream.parallelize()
in java for apprach#2 to make the changes but the runtime was increasing. What am I doing wrong?
The goal is to get the runtime less than approach #3. Is there a way in C to parallelize this and solve in lesser time using pthreads?
java c multithreading
The problem statement is that we have a string and we want to rotate each character to its next character i.e a
to b
, b
to c
and z
to a
. Also, the conversion is based on the number x ( x is <= size of string). The number represents the length of the characters to be converted. Let's say the number is 3 and string is stack
which means only first 3 characters need to be converted, so output will be tubck
. if the number is 5 then the output will be tubdl
.
I am running the solution for 100000000
times and generating the variable number
randomly. I have solved this problem using 3 approaches mentioned below:
- Convert from character to integer, then increment the integer by 1, then convert the integer back to character.
- Using the hashmap to get the updated character value in O(1) time.
- Using C, but the approach followed is same as of step # 1
The runtime of the hashmap technique (approach 2) is coming to be more. I don't know why?
Approach #1 is
public static void main(String args) {
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(26) + 1; j++) {
if (stringCharArray[j] == 'z') {
stringCharArray[j] = 'a';
} else {
stringCharArray[j] = (char) (((int) (stringCharArray[j])) + 1);
}
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach # 2 using hashmap is
public static void main(String args) {
HashMap hashMap = new HashMap();
hashMap.put('a', 'b');
hashMap.put('b', 'c');
hashMap.put('c', 'd');
hashMap.put('d', 'e');
hashMap.put('e', 'f');
hashMap.put('f', 'g');
hashMap.put('g', 'h');
hashMap.put('h', 'i');
hashMap.put('i', 'j');
hashMap.put('j', 'k');
hashMap.put('k', 'l');
hashMap.put('l', 'm');
hashMap.put('m', 'n');
hashMap.put('n', 'o');
hashMap.put('o', 'p');
hashMap.put('p', 'q');
hashMap.put('q', 'r');
hashMap.put('r', 's');
hashMap.put('s', 't');
hashMap.put('t', 'u');
hashMap.put('u', 'v');
hashMap.put('v', 'w');
hashMap.put('w', 'x');
hashMap.put('x', 'y');
hashMap.put('y', 'z');
hashMap.put('z', 'a');
Long startTime = System.currentTimeMillis();
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (Integer i = 0; i <100000000; i++) {
{
for (Integer j = 0; j < random.nextInt(26) + 1; j++) {
stringCharArray[j] = (char) hashMap.get(stringCharArray[j]);
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
}
Approach #3
#include <stdio.h>
#include <time.h>
#include <zconf.h>
#include <stdlib.h>
int main() {
long start = clock();
char name = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < rand() % 25; j++) {
if (name[j] == 'z') {
name[j] = 'a';
} else {
name[j] = (char) (((int) (name[j])) + 1);
}
}
}
}
long stop = clock();
printf("time taken = %ld sec n",( stop-start)/1000);
}
The runtime of approach 1 is ~ 8150 m, approach 2 is ~ 9700 ms and approach 3 is ~ 5400 ms. I am using MacBook Pro 2.3 GHz Intel Core i5 with 8 GB 2133 MHz LPDDR3.
How do I reduce this runtime, I used stream.parallelize()
in java for apprach#2 to make the changes but the runtime was increasing. What am I doing wrong?
The goal is to get the runtime less than approach #3. Is there a way in C to parallelize this and solve in lesser time using pthreads?
java c multithreading
java c multithreading
edited Jan 3 at 9:12
Jarod42
119k12104189
119k12104189
asked Jan 3 at 8:29


Amarjit SinghAmarjit Singh
1,0072728
1,0072728
1
Did you check how much time the programme spent in random functions ? Note also that all approaches are O(1)
– Damien
Jan 3 at 8:38
4
A better approach than theHashMap
approach (which necessarily requires boxing) is to populate an array (or even aString
):"bcde...xyza".charAt(name[0] - 'a')
.
– Andy Turner
Jan 3 at 8:43
1
for (int j = 0; j < random.nextInt(26) + 1; j++)
will callnextint
upon each iteation. I don't think you want that, so have a line before the for loop, e.g.int n=random.nextInt(26)+1;
and thenfor (int j = 0; j < n; j++)
This also optimizes the code because it eliminates unnecessary function calls.
– Paul Ogilvie
Jan 3 at 9:09
1
Notice thanfor (int j = 0; j < rand() % 25; j++)
would callrand()
at each iteration, you probably want:const int end = rand() % 25; for (int j = 0; j != end; j++)
.
– Jarod42
Jan 3 at 9:10
1
Instead of usingstringCharArray[j]
, use a pointer variable. This optimizes the code by eliminating indexing instructions.
– Paul Ogilvie
Jan 3 at 9:12
|
show 3 more comments
1
Did you check how much time the programme spent in random functions ? Note also that all approaches are O(1)
– Damien
Jan 3 at 8:38
4
A better approach than theHashMap
approach (which necessarily requires boxing) is to populate an array (or even aString
):"bcde...xyza".charAt(name[0] - 'a')
.
– Andy Turner
Jan 3 at 8:43
1
for (int j = 0; j < random.nextInt(26) + 1; j++)
will callnextint
upon each iteation. I don't think you want that, so have a line before the for loop, e.g.int n=random.nextInt(26)+1;
and thenfor (int j = 0; j < n; j++)
This also optimizes the code because it eliminates unnecessary function calls.
– Paul Ogilvie
Jan 3 at 9:09
1
Notice thanfor (int j = 0; j < rand() % 25; j++)
would callrand()
at each iteration, you probably want:const int end = rand() % 25; for (int j = 0; j != end; j++)
.
– Jarod42
Jan 3 at 9:10
1
Instead of usingstringCharArray[j]
, use a pointer variable. This optimizes the code by eliminating indexing instructions.
– Paul Ogilvie
Jan 3 at 9:12
1
1
Did you check how much time the programme spent in random functions ? Note also that all approaches are O(1)
– Damien
Jan 3 at 8:38
Did you check how much time the programme spent in random functions ? Note also that all approaches are O(1)
– Damien
Jan 3 at 8:38
4
4
A better approach than the
HashMap
approach (which necessarily requires boxing) is to populate an array (or even a String
): "bcde...xyza".charAt(name[0] - 'a')
.– Andy Turner
Jan 3 at 8:43
A better approach than the
HashMap
approach (which necessarily requires boxing) is to populate an array (or even a String
): "bcde...xyza".charAt(name[0] - 'a')
.– Andy Turner
Jan 3 at 8:43
1
1
for (int j = 0; j < random.nextInt(26) + 1; j++)
will call nextint
upon each iteation. I don't think you want that, so have a line before the for loop, e.g. int n=random.nextInt(26)+1;
and then for (int j = 0; j < n; j++)
This also optimizes the code because it eliminates unnecessary function calls.– Paul Ogilvie
Jan 3 at 9:09
for (int j = 0; j < random.nextInt(26) + 1; j++)
will call nextint
upon each iteation. I don't think you want that, so have a line before the for loop, e.g. int n=random.nextInt(26)+1;
and then for (int j = 0; j < n; j++)
This also optimizes the code because it eliminates unnecessary function calls.– Paul Ogilvie
Jan 3 at 9:09
1
1
Notice than
for (int j = 0; j < rand() % 25; j++)
would call rand()
at each iteration, you probably want: const int end = rand() % 25; for (int j = 0; j != end; j++)
.– Jarod42
Jan 3 at 9:10
Notice than
for (int j = 0; j < rand() % 25; j++)
would call rand()
at each iteration, you probably want: const int end = rand() % 25; for (int j = 0; j != end; j++)
.– Jarod42
Jan 3 at 9:10
1
1
Instead of using
stringCharArray[j]
, use a pointer variable. This optimizes the code by eliminating indexing instructions.– Paul Ogilvie
Jan 3 at 9:12
Instead of using
stringCharArray[j]
, use a pointer variable. This optimizes the code by eliminating indexing instructions.– Paul Ogilvie
Jan 3 at 9:12
|
show 3 more comments
2 Answers
2
active
oldest
votes
Here's a version that is 8x faster on my PC than your C example.
#include <immintrin.h>
int main()
{
const __m256i compareConstant = _mm256_setr_epi8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 );
long start = clock();
char name[ 32 ] = "abcdefghijklmnopqrstuvwxyz";
// __m256i is a C name for AVX register.
// AVX registers are 32 bytes in size, so your 26 bytes string fits in just a single one.
// The following line loads your string from memory to that register.
__m256i n = _mm256_loadu_si256( ( const __m256i* )name );
for( int i = 0; i < 100000000; i++ )
{
// Increment the letters, all 32 of them.
// `_mm256_set1_epi8` creates a value with all 32 bytes set to the same value.
// `_mm256_add_epi8` adds one set of 32 signed bytes to another set of 32 signed bytes.
// It's not a loop i.e. it's very fast, CPUs can actually run 2-3 such instructions per cycle.
__m256i n2 = _mm256_add_epi8( n, _mm256_set1_epi8( 1 ) );
// Wrap any > 'z' letters back to 'a'
// _mm256_cmpgt_epi8 compares one set of bytes to another set, for `>`.
// When it's `>` the result byte is set to 0xFF, when it's `<=` the result byte is 0.
// _mm256_blendv_epi8 combines bytes from 2 registers based on the bytes from the third one.
// In this case, the third one is the result of the comparison.
n2 = _mm256_blendv_epi8( n2, _mm256_set1_epi8( 'a' ), _mm256_cmpgt_epi8( n2, _mm256_set1_epi8( 'z' ) ) );
// Combine incremented ones with old, using random number of first characters
const int r = rand() % 25;
// This sets all 32 bytes in rv to the random number r
__m256i rv = _mm256_broadcastb_epi8( _mm_cvtsi32_si128( r ) );
// Compares all bytes in rv with the constant value [0, 1, 2, 3, ...]
// For bytes where r>cc, blendv_epi8 will select a byte from n2.
// For bytes where r<=cc, n will not change because blendv_epi8 will select an old value.
n = _mm256_blendv_epi8( n, n2, _mm256_cmpgt_epi8( rv, compareConstant ) );
}
long stop = clock();
printf( "time taken = %ld sec n", ( stop - start ) / 1000 );
}
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
1
Notice that you callrand()
only once by loop which should also help a lot :-)
– Jarod42
Jan 3 at 9:28
1
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
|
show 3 more comments
Define a character array like
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
And you can get next either by directly accessing same index or by difference in ascii of characters
stringCharArray[j] = nextChar[j];//by index
stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
Complete code is below
Long startTime = System.currentTimeMillis();
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(27); j++) {
stringCharArray[j] = nextChar[j];//by index
//stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54018711%2freduce-runtime-for-manipulating-string-multiple-times-using-hashmap-other-meth%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here's a version that is 8x faster on my PC than your C example.
#include <immintrin.h>
int main()
{
const __m256i compareConstant = _mm256_setr_epi8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 );
long start = clock();
char name[ 32 ] = "abcdefghijklmnopqrstuvwxyz";
// __m256i is a C name for AVX register.
// AVX registers are 32 bytes in size, so your 26 bytes string fits in just a single one.
// The following line loads your string from memory to that register.
__m256i n = _mm256_loadu_si256( ( const __m256i* )name );
for( int i = 0; i < 100000000; i++ )
{
// Increment the letters, all 32 of them.
// `_mm256_set1_epi8` creates a value with all 32 bytes set to the same value.
// `_mm256_add_epi8` adds one set of 32 signed bytes to another set of 32 signed bytes.
// It's not a loop i.e. it's very fast, CPUs can actually run 2-3 such instructions per cycle.
__m256i n2 = _mm256_add_epi8( n, _mm256_set1_epi8( 1 ) );
// Wrap any > 'z' letters back to 'a'
// _mm256_cmpgt_epi8 compares one set of bytes to another set, for `>`.
// When it's `>` the result byte is set to 0xFF, when it's `<=` the result byte is 0.
// _mm256_blendv_epi8 combines bytes from 2 registers based on the bytes from the third one.
// In this case, the third one is the result of the comparison.
n2 = _mm256_blendv_epi8( n2, _mm256_set1_epi8( 'a' ), _mm256_cmpgt_epi8( n2, _mm256_set1_epi8( 'z' ) ) );
// Combine incremented ones with old, using random number of first characters
const int r = rand() % 25;
// This sets all 32 bytes in rv to the random number r
__m256i rv = _mm256_broadcastb_epi8( _mm_cvtsi32_si128( r ) );
// Compares all bytes in rv with the constant value [0, 1, 2, 3, ...]
// For bytes where r>cc, blendv_epi8 will select a byte from n2.
// For bytes where r<=cc, n will not change because blendv_epi8 will select an old value.
n = _mm256_blendv_epi8( n, n2, _mm256_cmpgt_epi8( rv, compareConstant ) );
}
long stop = clock();
printf( "time taken = %ld sec n", ( stop - start ) / 1000 );
}
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
1
Notice that you callrand()
only once by loop which should also help a lot :-)
– Jarod42
Jan 3 at 9:28
1
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
|
show 3 more comments
Here's a version that is 8x faster on my PC than your C example.
#include <immintrin.h>
int main()
{
const __m256i compareConstant = _mm256_setr_epi8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 );
long start = clock();
char name[ 32 ] = "abcdefghijklmnopqrstuvwxyz";
// __m256i is a C name for AVX register.
// AVX registers are 32 bytes in size, so your 26 bytes string fits in just a single one.
// The following line loads your string from memory to that register.
__m256i n = _mm256_loadu_si256( ( const __m256i* )name );
for( int i = 0; i < 100000000; i++ )
{
// Increment the letters, all 32 of them.
// `_mm256_set1_epi8` creates a value with all 32 bytes set to the same value.
// `_mm256_add_epi8` adds one set of 32 signed bytes to another set of 32 signed bytes.
// It's not a loop i.e. it's very fast, CPUs can actually run 2-3 such instructions per cycle.
__m256i n2 = _mm256_add_epi8( n, _mm256_set1_epi8( 1 ) );
// Wrap any > 'z' letters back to 'a'
// _mm256_cmpgt_epi8 compares one set of bytes to another set, for `>`.
// When it's `>` the result byte is set to 0xFF, when it's `<=` the result byte is 0.
// _mm256_blendv_epi8 combines bytes from 2 registers based on the bytes from the third one.
// In this case, the third one is the result of the comparison.
n2 = _mm256_blendv_epi8( n2, _mm256_set1_epi8( 'a' ), _mm256_cmpgt_epi8( n2, _mm256_set1_epi8( 'z' ) ) );
// Combine incremented ones with old, using random number of first characters
const int r = rand() % 25;
// This sets all 32 bytes in rv to the random number r
__m256i rv = _mm256_broadcastb_epi8( _mm_cvtsi32_si128( r ) );
// Compares all bytes in rv with the constant value [0, 1, 2, 3, ...]
// For bytes where r>cc, blendv_epi8 will select a byte from n2.
// For bytes where r<=cc, n will not change because blendv_epi8 will select an old value.
n = _mm256_blendv_epi8( n, n2, _mm256_cmpgt_epi8( rv, compareConstant ) );
}
long stop = clock();
printf( "time taken = %ld sec n", ( stop - start ) / 1000 );
}
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
1
Notice that you callrand()
only once by loop which should also help a lot :-)
– Jarod42
Jan 3 at 9:28
1
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
|
show 3 more comments
Here's a version that is 8x faster on my PC than your C example.
#include <immintrin.h>
int main()
{
const __m256i compareConstant = _mm256_setr_epi8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 );
long start = clock();
char name[ 32 ] = "abcdefghijklmnopqrstuvwxyz";
// __m256i is a C name for AVX register.
// AVX registers are 32 bytes in size, so your 26 bytes string fits in just a single one.
// The following line loads your string from memory to that register.
__m256i n = _mm256_loadu_si256( ( const __m256i* )name );
for( int i = 0; i < 100000000; i++ )
{
// Increment the letters, all 32 of them.
// `_mm256_set1_epi8` creates a value with all 32 bytes set to the same value.
// `_mm256_add_epi8` adds one set of 32 signed bytes to another set of 32 signed bytes.
// It's not a loop i.e. it's very fast, CPUs can actually run 2-3 such instructions per cycle.
__m256i n2 = _mm256_add_epi8( n, _mm256_set1_epi8( 1 ) );
// Wrap any > 'z' letters back to 'a'
// _mm256_cmpgt_epi8 compares one set of bytes to another set, for `>`.
// When it's `>` the result byte is set to 0xFF, when it's `<=` the result byte is 0.
// _mm256_blendv_epi8 combines bytes from 2 registers based on the bytes from the third one.
// In this case, the third one is the result of the comparison.
n2 = _mm256_blendv_epi8( n2, _mm256_set1_epi8( 'a' ), _mm256_cmpgt_epi8( n2, _mm256_set1_epi8( 'z' ) ) );
// Combine incremented ones with old, using random number of first characters
const int r = rand() % 25;
// This sets all 32 bytes in rv to the random number r
__m256i rv = _mm256_broadcastb_epi8( _mm_cvtsi32_si128( r ) );
// Compares all bytes in rv with the constant value [0, 1, 2, 3, ...]
// For bytes where r>cc, blendv_epi8 will select a byte from n2.
// For bytes where r<=cc, n will not change because blendv_epi8 will select an old value.
n = _mm256_blendv_epi8( n, n2, _mm256_cmpgt_epi8( rv, compareConstant ) );
}
long stop = clock();
printf( "time taken = %ld sec n", ( stop - start ) / 1000 );
}
Here's a version that is 8x faster on my PC than your C example.
#include <immintrin.h>
int main()
{
const __m256i compareConstant = _mm256_setr_epi8( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 );
long start = clock();
char name[ 32 ] = "abcdefghijklmnopqrstuvwxyz";
// __m256i is a C name for AVX register.
// AVX registers are 32 bytes in size, so your 26 bytes string fits in just a single one.
// The following line loads your string from memory to that register.
__m256i n = _mm256_loadu_si256( ( const __m256i* )name );
for( int i = 0; i < 100000000; i++ )
{
// Increment the letters, all 32 of them.
// `_mm256_set1_epi8` creates a value with all 32 bytes set to the same value.
// `_mm256_add_epi8` adds one set of 32 signed bytes to another set of 32 signed bytes.
// It's not a loop i.e. it's very fast, CPUs can actually run 2-3 such instructions per cycle.
__m256i n2 = _mm256_add_epi8( n, _mm256_set1_epi8( 1 ) );
// Wrap any > 'z' letters back to 'a'
// _mm256_cmpgt_epi8 compares one set of bytes to another set, for `>`.
// When it's `>` the result byte is set to 0xFF, when it's `<=` the result byte is 0.
// _mm256_blendv_epi8 combines bytes from 2 registers based on the bytes from the third one.
// In this case, the third one is the result of the comparison.
n2 = _mm256_blendv_epi8( n2, _mm256_set1_epi8( 'a' ), _mm256_cmpgt_epi8( n2, _mm256_set1_epi8( 'z' ) ) );
// Combine incremented ones with old, using random number of first characters
const int r = rand() % 25;
// This sets all 32 bytes in rv to the random number r
__m256i rv = _mm256_broadcastb_epi8( _mm_cvtsi32_si128( r ) );
// Compares all bytes in rv with the constant value [0, 1, 2, 3, ...]
// For bytes where r>cc, blendv_epi8 will select a byte from n2.
// For bytes where r<=cc, n will not change because blendv_epi8 will select an old value.
n = _mm256_blendv_epi8( n, n2, _mm256_cmpgt_epi8( rv, compareConstant ) );
}
long stop = clock();
printf( "time taken = %ld sec n", ( stop - start ) / 1000 );
}
edited Jan 3 at 9:48
answered Jan 3 at 9:16
SoontsSoonts
9,10083576
9,10083576
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
1
Notice that you callrand()
only once by loop which should also help a lot :-)
– Jarod42
Jan 3 at 9:28
1
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
|
show 3 more comments
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
1
Notice that you callrand()
only once by loop which should also help a lot :-)
– Jarod42
Jan 3 at 9:28
1
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
Can you please explain what you are doing and where these instructions come from (compiler, library,...)?
– Paul Ogilvie
Jan 3 at 9:17
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
@PaulOgilvie Re-implemented OP's code with AVX2 SIMD. The instructions are built-in in CPUs made after 2013, and are supported by all modern C and C++ compilers. As you see, performance difference is huge.
– Soonts
Jan 3 at 9:22
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
Thanks a lot for this code. I think I need a guide to understand this. U seem to be very well versed coder in C.
– Amarjit Singh
Jan 3 at 9:23
1
1
Notice that you call
rand()
only once by loop which should also help a lot :-)– Jarod42
Jan 3 at 9:28
Notice that you call
rand()
only once by loop which should also help a lot :-)– Jarod42
Jan 3 at 9:28
1
1
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
@AmarjitSingh Added more comments, hope it's simpler to understand now.
– Soonts
Jan 3 at 9:56
|
show 3 more comments
Define a character array like
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
And you can get next either by directly accessing same index or by difference in ascii of characters
stringCharArray[j] = nextChar[j];//by index
stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
Complete code is below
Long startTime = System.currentTimeMillis();
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(27); j++) {
stringCharArray[j] = nextChar[j];//by index
//stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
add a comment |
Define a character array like
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
And you can get next either by directly accessing same index or by difference in ascii of characters
stringCharArray[j] = nextChar[j];//by index
stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
Complete code is below
Long startTime = System.currentTimeMillis();
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(27); j++) {
stringCharArray[j] = nextChar[j];//by index
//stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
add a comment |
Define a character array like
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
And you can get next either by directly accessing same index or by difference in ascii of characters
stringCharArray[j] = nextChar[j];//by index
stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
Complete code is below
Long startTime = System.currentTimeMillis();
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(27); j++) {
stringCharArray[j] = nextChar[j];//by index
//stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
Define a character array like
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
And you can get next either by directly accessing same index or by difference in ascii of characters
stringCharArray[j] = nextChar[j];//by index
stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
Complete code is below
Long startTime = System.currentTimeMillis();
char nextChar = {'b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a'};
String name = "abcdefghijklmnopqrstuvwxyz";
char stringCharArray = name.toCharArray();
Random random = new Random();
for (int i = 0; i <100000000; i++) {
{
for (int j = 0; j < random.nextInt(27); j++) {
stringCharArray[j] = nextChar[j];//by index
//stringCharArray[j] = nextChar[stringCharArray[j]-'a'];// using ascii
}
}
}
Long endtime = System.currentTimeMillis();
System.out.println(endtime-startTime+" ms");
edited Jan 3 at 9:00
answered Jan 3 at 8:53


NGVNGV
2,18122040
2,18122040
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
add a comment |
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
Thanks a lot. I used this in C. The time reduced from ~5400 to ~5350. Definitely, there is some improvement.
– Amarjit Singh
Jan 3 at 9:01
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54018711%2freduce-runtime-for-manipulating-string-multiple-times-using-hashmap-other-meth%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
p,cDMLDQxAJ9ItiqeUvN8eePVD73XrSthu93p 7mboxDl4pjY TE6t1qoI
1
Did you check how much time the programme spent in random functions ? Note also that all approaches are O(1)
– Damien
Jan 3 at 8:38
4
A better approach than the
HashMap
approach (which necessarily requires boxing) is to populate an array (or even aString
):"bcde...xyza".charAt(name[0] - 'a')
.– Andy Turner
Jan 3 at 8:43
1
for (int j = 0; j < random.nextInt(26) + 1; j++)
will callnextint
upon each iteation. I don't think you want that, so have a line before the for loop, e.g.int n=random.nextInt(26)+1;
and thenfor (int j = 0; j < n; j++)
This also optimizes the code because it eliminates unnecessary function calls.– Paul Ogilvie
Jan 3 at 9:09
1
Notice than
for (int j = 0; j < rand() % 25; j++)
would callrand()
at each iteration, you probably want:const int end = rand() % 25; for (int j = 0; j != end; j++)
.– Jarod42
Jan 3 at 9:10
1
Instead of using
stringCharArray[j]
, use a pointer variable. This optimizes the code by eliminating indexing instructions.– Paul Ogilvie
Jan 3 at 9:12