Unable to make code work in Jmeter´s Beanshell PreProcessor - javascript

I´m doing some web scraping using Apache Jmeter´s built-in WebDriver Sampler (with Javascript).
Before the test starts, I need to execute a certain amount of functions in order to build a specific user ID that matches some frontend validations.
In order to do so, I´m declaring and using those functions in each script block provided by the WebDriver sampler.
Since, those functions I need to run do only need to be executed once in the entire test plan (just as it starts), I was wondering if there was a way to use those functions in a BeanShell PreProcessor. Since my code works but was originally made on Javascript, I tried translating it to Java in order to be able to use them in Beanshell.
I keep getting the following error when I run the test:
ERROR o.a.j.u.BeanShellInterpreter:
Error invoking bsh method: eval Sourced file: inline evaluation of: ``//String DICTIONARY = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String[] DICTIONARY = {"A"," . . . '' : Typed variable declaration : Typed variable declaration : Typed variable declaration
My original javascript code is the following (this one works when used at WebDriver Sampler´s code block):
var DICTIONARY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
function generateRandomString(length, dictionary) {
var result = '';
for ( var i = 0; i < length; i++ ) {
result += dictionary.charAt(Math.floor(Math.random() * dictionary.length));
}
return result;
}
function countChars(character, sentence){
var count = 0
for(var i=0; i<sentence.length; i++) {
if (sentence[i] === character) count++
}
return count
}
function hasConsecutivesChars(sentence, length) {
var charCounter = {}
for (var i = 0; i < sentence.length; i++) {
var currentChar = sentence[i]
if (countChars(currentChar, sentence) >= length) {
return true
}
}
return false
}
function generateRandomStringWithoutConsecutivesChars(length, maxConsecutiveChars, dictionary, maxTries) {
var isValidString = false
var randomString = ''
var tries = 0;
while(!isValidString && tries <= maxTries) {
randomString = generateRandomString(length, dictionary)
var isValidString = !hasConsecutivesChars(randomString, maxConsecutiveChars)
tries++;
}
return randomString
}
function randomIntFromInterval(min, max) { // mínimo y máximo incluidos
return Math.floor(Math.random() * (max - min + 1) + min)
}
var nombreUsuario = "SELENIUM_" + generateRandomStringWithoutConsecutivesChars(5, 3, DICTIONARY, 100) + randomIntFromInterval(1, 9);
And here is the same code translated into java and implemented in BeanShell PreProcessor (the one that´s failing):
String[] DICTIONARY = {"A","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"};
String generateRandomString(int length, String[] dictionary) {
String result = "";
for ( int i = 0; i < length; i++ ) {
//result += dictionary.charAt(Math.floor(Math.random() * dictionary.length));
result += dictionary[Math.floor(Math.random() * 26)];
}
return result;
}
int countChars(String character, String sentence){
int count = 0;
for(int i=0; i<5; i++) {
//if (sentence[i] == character){
if (sentence.charAt(i) == character){
count++;
}
}
return count;
}
boolean hasConsecutivesChars(String sentence, int length) {
for (int i = 0; i < 5; i++) {
String currentChar = sentence.charAt(i);
if (countChars(currentChar, sentence) >= length) {
return true;
}
}
return false;
}
String generateRandomStringWithoutConsecutivesChars(int length, int maxConsecutiveChars, String[] dictionary, int maxTries) {
boolean isValidString = false;
String randomString = "";
int tries = 0;
while(!isValidString && tries <= maxTries) {
String randomString = generateRandomString(length, dictionary);
boolean isValidString = !hasConsecutivesChars(randomString, maxConsecutiveChars);
tries++;
}
return randomString;
}
int randomIntFromInterval(int min, int max) { // mínimo y máximo incluidos
return Math.floor(Math.random() * (max - min + 1) + min);
}
String id = generateRandomStringWithoutConsecutivesChars(5, 3, DICTIONARY, 100) + randomIntFromInterval(1, 9);
vars.put("id", id);
log.info(id);
Side Note: You´ll notice the translated code isn´t exactly the same as its original javascript counterpart. Those are some changes I made because I can´t access the string's length in Java, like i did in javascript.
Also, please excuse me for my rusty english, it´s not my mother tongue.
Thank you all in advance!

First of all are you aware or RandomStringUtils class which comes with JMeter?
If you still want to re-invent the wheel be informed that since JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting so consider switching to the JSR223 PreProcessor and the code like:
String[] DICTIONARY = ["A", "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"];
String generateRandomString(int length, String[] dictionary) {
String result = "";
for (int i = 0; i < length; i++) {
//result += dictionary.charAt(Math.floor(Math.random() * dictionary.length));
result += dictionary[Math.floor(Math.random() * 26) as int];
}
return result;
}
int countChars(String character, String sentence) {
int count = 0;
for (int i = 0; i < 5; i++) {
//if (sentence[i] == character){
if (sentence.charAt(i) == character as char) {
count++;
}
}
return count;
}
boolean hasConsecutivesChars(String sentence, int length) {
for (int i = 0; i < 5; i++) {
String currentChar = sentence.charAt(i);
if (countChars(currentChar, sentence) >= length) {
return true;
}
}
return false;
}
String generateRandomStringWithoutConsecutivesChars(int length, int maxConsecutiveChars, String[] dictionary, int maxTries) {
boolean isValidString = false;
String randomString = "";
int tries = 0;
while (!isValidString && tries <= maxTries) {
randomString = generateRandomString(length, dictionary);
isValidString = !hasConsecutivesChars(randomString, maxConsecutiveChars);
tries++;
}
return randomString;
}
int randomIntFromInterval(int min, int max) { // mínimo y máximo incluidos
return Math.floor(Math.random() * (max - min + 1) + min);
}
String id = generateRandomStringWithoutConsecutivesChars(5, 3, DICTIONARY, 100) + randomIntFromInterval(1, 9);
vars.put("id", id);
log.info(id);

Related

looking for an optimal solution to finding pairs in an array base on certain condition in Javascript [duplicate]

Given array of n integers and given a number X, find all the unique pairs of elements (a,b), whose summation is equal to X.
The following is my solution, it is O(nLog(n)+n), but I am not sure whether or not it is optimal.
int main(void)
{
int arr [10] = {1,2,3,4,5,6,7,8,9,0};
findpair(arr, 10, 7);
}
void findpair(int arr[], int len, int sum)
{
std::sort(arr, arr+len);
int i = 0;
int j = len -1;
while( i < j){
while((arr[i] + arr[j]) <= sum && i < j)
{
if((arr[i] + arr[j]) == sum)
cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
i++;
}
j--;
while((arr[i] + arr[j]) >= sum && i < j)
{
if((arr[i] + arr[j]) == sum)
cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
j--;
}
}
}
There are 3 approaches to this solution:
Let the sum be T and n be the size of array
Approach 1:
The naive way to do this would be to check all combinations (n choose 2). This exhaustive search is O(n2).
Approach 2:
A better way would be to sort the array. This takes O(n log n)
Then for each x in array A,
use binary search to look for T-x. This will take O(nlogn).
So, overall search is O(n log n)
Approach 3 :
The best way
would be to insert every element into a hash table (without sorting). This takes O(n) as constant time insertion.
Then for every x,
we can just look up its complement, T-x, which is O(1).
Overall the run time of this approach is O(n).
You can refer more here.Thanks.
# Let arr be the given array.
# And K be the give sum
for i=0 to arr.length - 1 do
# key is the element and value is its index.
hash(arr[i]) = i
end-for
for i=0 to arr.length - 1 do
# if K-th element exists and it's different then we found a pair
if hash(K - arr[i]) != i
print "pair i , hash(K - arr[i]) has sum K"
end-if
end-for
Implementation in Java : Using codaddict's algorithm (Maybe slightly different)
import java.util.HashMap;
public class ArrayPairSum {
public static void main(String[] args) {
int []a = {2,45,7,3,5,1,8,9};
printSumPairs(a,10);
}
public static void printSumPairs(int []input, int k){
Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();
for(int i=0;i<input.length;i++){
if(pairs.containsKey(input[i]))
System.out.println(input[i] +", "+ pairs.get(input[i]));
else
pairs.put(k-input[i], input[i]);
}
}
}
For input = {2,45,7,3,5,1,8,9} and if Sum is 10
Output pairs:
3,7
8,2
9,1
Some notes about the solution :
We iterate only once through the array --> O(n) time
Insertion and lookup time in Hash is O(1).
Overall time is O(n), although it uses extra space in terms of hash.
Solution in java. You can add all the String elements to an ArrayList of strings and return the list. Here I am just printing it out.
void numberPairsForSum(int[] array, int sum) {
HashSet<Integer> set = new HashSet<Integer>();
for (int num : array) {
if (set.contains(sum - num)) {
String s = num + ", " + (sum - num) + " add up to " + sum;
System.out.println(s);
}
set.add(num);
}
}
Python Implementation:
import itertools
list = [1, 1, 2, 3, 4, 5,]
uniquelist = set(list)
targetsum = 5
for n in itertools.combinations(uniquelist, 2):
if n[0] + n[1] == targetsum:
print str(n[0]) + " + " + str(n[1])
Output:
1 + 4
2 + 3
C++11, run time complexity O(n):
#include <vector>
#include <unordered_map>
#include <utility>
std::vector<std::pair<int, int>> FindPairsForSum(
const std::vector<int>& data, const int& sum)
{
std::unordered_map<int, size_t> umap;
std::vector<std::pair<int, int>> result;
for (size_t i = 0; i < data.size(); ++i)
{
if (0 < umap.count(sum - data[i]))
{
size_t j = umap[sum - data[i]];
result.push_back({data[i], data[j]});
}
else
{
umap[data[i]] = i;
}
}
return result;
}
Here is a solution witch takes into account duplicate entries. It is written in javascript and assumes array is sorted. The solution runs in O(n) time and does not use any extra memory aside from variable.
var count_pairs = function(_arr,x) {
if(!x) x = 0;
var pairs = 0;
var i = 0;
var k = _arr.length-1;
if((k+1)<2) return pairs;
var halfX = x/2;
while(i<k) {
var curK = _arr[k];
var curI = _arr[i];
var pairsThisLoop = 0;
if(curK+curI==x) {
// if midpoint and equal find combinations
if(curK==curI) {
var comb = 1;
while(--k>=i) pairs+=(comb++);
break;
}
// count pair and k duplicates
pairsThisLoop++;
while(_arr[--k]==curK) pairsThisLoop++;
// add k side pairs to running total for every i side pair found
pairs+=pairsThisLoop;
while(_arr[++i]==curI) pairs+=pairsThisLoop;
} else {
// if we are at a mid point
if(curK==curI) break;
var distK = Math.abs(halfX-curK);
var distI = Math.abs(halfX-curI);
if(distI > distK) while(_arr[++i]==curI);
else while(_arr[--k]==curK);
}
}
return pairs;
}
I solved this during an interview for a large corporation. They took it but not me.
So here it is for everyone.
Start at both side of the array and slowly work your way inwards making sure to count duplicates if they exist.
It only counts pairs but can be reworked to
find the pairs
find pairs < x
find pairs > x
Enjoy!
O(n)
def find_pairs(L,sum):
s = set(L)
edgeCase = sum/2
if L.count(edgeCase) ==2:
print edgeCase, edgeCase
s.remove(edgeCase)
for i in s:
diff = sum-i
if diff in s:
print i, diff
L = [2,45,7,3,5,1,8,9]
sum = 10
find_pairs(L,sum)
Methodology: a + b = c, so instead of looking for (a,b) we look for a = c -
b
Implementation in Java : Using codaddict's algorithm:
import java.util.Hashtable;
public class Range {
public static void main(String[] args) {
// TODO Auto-generated method stub
Hashtable mapping = new Hashtable();
int a[]= {80,79,82,81,84,83,85};
int k = 160;
for (int i=0; i < a.length; i++){
mapping.put(a[i], i);
}
for (int i=0; i < a.length; i++){
if (mapping.containsKey(k - a[i]) && (Integer)mapping.get(k-a[i]) != i){
System.out.println(k-a[i]+", "+ a[i]);
}
}
}
}
Output:
81, 79
79, 81
If you want duplicate pairs (eg: 80,80) also then just remove && (Integer)mapping.get(k-a[i]) != i from the if condition and you are good to go.
Just attended this question on HackerRank and here's my 'Objective C' Solution:
-(NSNumber*)sum:(NSArray*) a andK:(NSNumber*)k {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
long long count = 0;
for(long i=0;i<a.count;i++){
if(dict[a[i]]) {
count++;
NSLog(#"a[i]: %#, dict[array[i]]: %#", a[i], dict[a[i]]);
}
else{
NSNumber *calcNum = #(k.longLongValue-((NSNumber*)a[i]).longLongValue);
dict[calcNum] = a[i];
}
}
return #(count);
}
Hope it helps someone.
this is the implementation of O(n*lg n) using binary search implementation inside a loop.
#include <iostream>
using namespace std;
bool *inMemory;
int pairSum(int arr[], int n, int k)
{
int count = 0;
if(n==0)
return count;
for (int i = 0; i < n; ++i)
{
int start = 0;
int end = n-1;
while(start <= end)
{
int mid = start + (end-start)/2;
if(i == mid)
break;
else if((arr[i] + arr[mid]) == k && !inMemory[i] && !inMemory[mid])
{
count++;
inMemory[i] = true;
inMemory[mid] = true;
}
else if(arr[i] + arr[mid] >= k)
{
end = mid-1;
}
else
start = mid+1;
}
}
return count;
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
inMemory = new bool[10];
for (int i = 0; i < 10; ++i)
{
inMemory[i] = false;
}
cout << pairSum(arr, 10, 11) << endl;
return 0;
}
In python
arr = [1, 2, 4, 6, 10]
diff_hash = {}
expected_sum = 3
for i in arr:
if diff_hash.has_key(i):
print i, diff_hash[i]
key = expected_sum - i
diff_hash[key] = i
Nice solution from Codeaddict. I took the liberty of implementing a version of it in Ruby:
def find_sum(arr,sum)
result ={}
h = Hash[arr.map {|i| [i,i]}]
arr.each { |l| result[l] = sum-l if h[sum-l] && !result[sum-l] }
result
end
To allow duplicate pairs (1,5), (5,1) we just have to remove the && !result[sum-l] instruction
Here is Java code for three approaches:
1. Using Map O(n), HashSet can also be used here.
2. Sort array and then use BinarySearch to look for complement O(nLog(n))
3. Traditional BruteForce two loops O(n^2)
public class PairsEqualToSum {
public static void main(String[] args) {
int a[] = {1,10,5,8,2,12,6,4};
findPairs1(a,10);
findPairs2(a,10);
findPairs3(a,10);
}
//Method1 - O(N) use a Map to insert values as keys & check for number's complement in map
static void findPairs1(int[]a, int sum){
Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();
for(int i=0; i<a.length; i++){
if(pairs.containsKey(sum-a[i]))
System.out.println("("+a[i]+","+(sum-a[i])+")");
else
pairs.put(a[i], 0);
}
}
//Method2 - O(nlog(n)) using Sort
static void findPairs2(int[]a, int sum){
Arrays.sort(a);
for(int i=0; i<a.length/2; i++){
int complement = sum - a[i];
int foundAtIndex = Arrays.binarySearch(a,complement);
if(foundAtIndex >0 && foundAtIndex != i) //to avoid situation where binarySearch would find the original and not the complement like "5"
System.out.println("("+a[i]+","+(sum-a[i])+")");
}
}
//Method 3 - Brute Force O(n^2)
static void findPairs3(int[]a, int sum){
for(int i=0; i<a.length; i++){
for(int j=i; j<a.length;j++){
if(a[i]+a[j] == sum)
System.out.println("("+a[i]+","+a[j]+")");
}
}
}
}
A Simple program in java for arrays having unique elements:
import java.util.*;
public class ArrayPairSum {
public static void main(String[] args) {
int []a = {2,4,7,3,5,1,8,9,5};
sumPairs(a,10);
}
public static void sumPairs(int []input, int k){
Set<Integer> set = new HashSet<Integer>();
for(int i=0;i<input.length;i++){
if(set.contains(input[i]))
System.out.println(input[i] +", "+(k-input[i]));
else
set.add(k-input[i]);
}
}
}
A simple Java code snippet for printing the pairs below:
public static void count_all_pairs_with_given_sum(int arr[], int S){
if(arr.length < 2){
return;
}
HashSet values = new HashSet(arr.length);
for(int value : arr)values.add(value);
for(int value : arr){
int difference = S - value;
if(values.contains(difference) && value<difference){
System.out.printf("(%d, %d) %n", value, difference);
}
}
}
Another solution in Swift: the idea is to create an hash that store values of (sum - currentValue) and compare this to the current value of the loop. The complexity is O(n).
func findPair(list: [Int], _ sum: Int) -> [(Int, Int)]? {
var hash = Set<Int>() //save list of value of sum - item.
var dictCount = [Int: Int]() //to avoid the case A*2 = sum where we have only one A in the array
var foundKeys = Set<Int>() //to avoid duplicated pair in the result.
var result = [(Int, Int)]() //this is for the result.
for item in list {
//keep track of count of each element to avoid problem: [2, 3, 5], 10 -> result = (5,5)
if (!dictCount.keys.contains(item)) {
dictCount[item] = 1
} else {
dictCount[item] = dictCount[item]! + 1
}
//if my hash does not contain the (sum - item) value -> insert to hash.
if !hash.contains(sum-item) {
hash.insert(sum-item)
}
//check if current item is the same as another hash value or not, if yes, return the tuple.
if hash.contains(item) &&
(dictCount[item] > 1 || sum != item*2) // check if we have item*2 = sum or not.
{
if !foundKeys.contains(item) && !foundKeys.contains(sum-item) {
foundKeys.insert(item) //add to found items in order to not to add duplicated pair.
result.append((item, sum-item))
}
}
}
return result
}
//test:
let a = findPair([2,3,5,4,1,7,6,8,9,5,3,3,3,3,3,3,3,3,3], 14) //will return (8,6) and (9,5)
My Solution - Java - Without duplicates
public static void printAllPairSum(int[] a, int x){
System.out.printf("printAllPairSum(%s,%d)\n", Arrays.toString(a),x);
if(a==null||a.length==0){
return;
}
int length = a.length;
Map<Integer,Integer> reverseMapOfArray = new HashMap<>(length,1.0f);
for (int i = 0; i < length; i++) {
reverseMapOfArray.put(a[i], i);
}
for (int i = 0; i < length; i++) {
Integer j = reverseMapOfArray.get(x - a[i]);
if(j!=null && i<j){
System.out.printf("a[%d] + a[%d] = %d + %d = %d\n",i,j,a[i],a[j],x);
}
}
System.out.println("------------------------------");
}
This prints the pairs and avoids duplicates using bitwise manipulation.
public static void findSumHashMap(int[] arr, int key) {
Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
for(int i=0;i<arr.length;i++)
valMap.put(arr[i], i);
int indicesVisited = 0;
for(int i=0;i<arr.length;i++) {
if(valMap.containsKey(key - arr[i]) && valMap.get(key - arr[i]) != i) {
if(!((indicesVisited & ((1<<i) | (1<<valMap.get(key - arr[i])))) > 0)) {
int diff = key-arr[i];
System.out.println(arr[i] + " " +diff);
indicesVisited = indicesVisited | (1<<i) | (1<<valMap.get(key - arr[i]));
}
}
}
}
I bypassed the bit manuplation and just compared the index values. This is less than the loop iteration value (i in this case). This will not print the duplicate pairs and duplicate array elements also.
public static void findSumHashMap(int[] arr, int key) {
Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
valMap.put(arr[i], i);
}
for (int i = 0; i < arr.length; i++) {
if (valMap.containsKey(key - arr[i])
&& valMap.get(key - arr[i]) != i) {
if (valMap.get(key - arr[i]) < i) {
int diff = key - arr[i];
System.out.println(arr[i] + " " + diff);
}
}
}
}
in C#:
int[] array = new int[] { 1, 5, 7, 2, 9, 8, 4, 3, 6 }; // given array
int sum = 10; // given sum
for (int i = 0; i <= array.Count() - 1; i++)
if (array.Contains(sum - array[i]))
Console.WriteLine("{0}, {1}", array[i], sum - array[i]);
One Solution can be this, but not optimul (The complexity of this code is O(n^2)):
public class FindPairsEqualToSum {
private static int inputSum = 0;
public static List<String> findPairsForSum(int[] inputArray, int sum) {
List<String> list = new ArrayList<String>();
List<Integer> inputList = new ArrayList<Integer>();
for (int i : inputArray) {
inputList.add(i);
}
for (int i : inputArray) {
int tempInt = sum - i;
if (inputList.contains(tempInt)) {
String pair = String.valueOf(i + ", " + tempInt);
list.add(pair);
}
}
return list;
}
}
A simple python version of the code that find a pair sum of zero and can be modify to find k:
def sumToK(lst):
k = 0 # <- define the k here
d = {} # build a dictionary
# build the hashmap key = val of lst, value = i
for index, val in enumerate(lst):
d[val] = index
# find the key; if a key is in the dict, and not the same index as the current key
for i, val in enumerate(lst):
if (k-val) in d and d[k-val] != i:
return True
return False
The run time complexity of the function is O(n) and Space: O(n) as well.
public static int[] f (final int[] nums, int target) {
int[] r = new int[2];
r[0] = -1;
r[1] = -1;
int[] vIndex = new int[0Xfff];
for (int i = 0; i < nums.length; i++) {
int delta = 0Xff;
int gapIndex = target - nums[i] + delta;
if (vIndex[gapIndex] != 0) {
r[0] = vIndex[gapIndex];
r[1] = i + 1;
return r;
} else {
vIndex[nums[i] + delta] = i + 1;
}
}
return r;
}
less than o(n) solution will be=>
function(array,k)
var map = {};
for element in array
map(element) = true;
if(map(k-element))
return {k,element}
Solution in Python using list comprehension
f= [[i,j] for i in list for j in list if j+i==X];
O(N2)
also gives two ordered pairs- (a,b) and (b,a) as well
I can do it in O(n). Let me know when you want the answer. Note it involves simply traversing the array once with no sorting, etc... I should mention too that it exploits commutativity of addition and doesn't use hashes but wastes memory.
using System;
using System.Collections.Generic;
/*
An O(n) approach exists by using a lookup table. The approach is to store the value in a "bin" that can easily be looked up(e.g., O(1)) if it is a candidate for an appropriate sum.
e.g.,
for each a[k] in the array we simply put the it in another array at the location x - a[k].
Suppose we have [0, 1, 5, 3, 6, 9, 8, 7] and x = 9
We create a new array,
indexes value
9 - 0 = 9 0
9 - 1 = 8 1
9 - 5 = 4 5
9 - 3 = 6 3
9 - 6 = 3 6
9 - 9 = 0 9
9 - 8 = 1 8
9 - 7 = 2 7
THEN the only values that matter are the ones who have an index into the new table.
So, say when we reach 9 or equal we see if our new array has the index 9 - 9 = 0. Since it does we know that all the values it contains will add to 9. (note in this cause it's obvious there is only 1 possible one but it might have multiple index values in it which we need to store).
So effectively what we end up doing is only having to move through the array once. Because addition is commutative we will end up with all the possible results.
For example, when we get to 6 we get the index into our new table as 9 - 6 = 3. Since the table contains that index value we know the values.
This is essentially trading off speed for memory.
*/
namespace sum
{
class Program
{
static void Main(string[] args)
{
int num = 25;
int X = 10;
var arr = new List<int>();
for(int i = 0; i <= num; i++) arr.Add((new Random((int)(DateTime.Now.Ticks + i*num))).Next(0, num*2));
Console.Write("["); for (int i = 0; i < num - 1; i++) Console.Write(arr[i] + ", "); Console.WriteLine(arr[arr.Count-1] + "] - " + X);
var arrbrute = new List<Tuple<int,int>>();
var arrfast = new List<Tuple<int,int>>();
for(int i = 0; i < num; i++)
for(int j = i+1; j < num; j++)
if (arr[i] + arr[j] == X)
arrbrute.Add(new Tuple<int, int>(arr[i], arr[j]));
int M = 500;
var lookup = new List<List<int>>();
for(int i = 0; i < 1000; i++) lookup.Add(new List<int>());
for(int i = 0; i < num; i++)
{
// Check and see if we have any "matches"
if (lookup[M + X - arr[i]].Count != 0)
{
foreach(var j in lookup[M + X - arr[i]])
arrfast.Add(new Tuple<int, int>(arr[i], arr[j]));
}
lookup[M + arr[i]].Add(i);
}
for(int i = 0; i < arrbrute.Count; i++)
Console.WriteLine(arrbrute[i].Item1 + " + " + arrbrute[i].Item2 + " = " + X);
Console.WriteLine("---------");
for(int i = 0; i < arrfast.Count; i++)
Console.WriteLine(arrfast[i].Item1 + " + " + arrfast[i].Item2 + " = " + X);
Console.ReadKey();
}
}
}
I implemented logic in Scala with out a Map. It gives duplicate pairs since the counter loops thru entire elements of the array. If duplicate pairs are needed, you can simply return the value pc
val arr = Array[Int](8, 7, 2, 5, 3, 1, 5)
val num = 10
var pc = 0
for(i <- arr.indices) {
if(arr.contains(Math.abs(arr(i) - num))) pc += 1
}
println(s"Pairs: ${pc/2}")
It is working with duplicates values in the array as well.
GOLANG Implementation
func findPairs(slice1 []int, sum int) [][]int {
pairMap := make(map[int]int)
var SliceOfPairs [][]int
for i, v := range slice1 {
if valuei, ok := pairMap[v]; ok {
//fmt.Println("Pair Found", i, valuei)
SliceOfPairs = append(SliceOfPairs, []int{i, valuei})
} else {
pairMap[sum-v] = i
}
}
return SliceOfPairs
}
function findPairOfNumbers(arr, targetSum) {
arr = arr.sort();
var low = 0, high = arr.length - 1, sum, result = [];
while(low < high) {
sum = arr[low] + arr[high];
if(sum < targetSum)
low++;
else if(sum > targetSum)
high--;
else if(sum === targetSum) {
result.push({val1: arr[low], val2: arr[high]});
high--;
}
}
return (result || false);
}
var pairs = findPairOfNumbers([1,2,3,4,5,6,7,8,9,0], 7);
if(pairs.length) {
console.log(pairs);
} else {
console.log("No pair of numbers found that sums to " + 7);
}

How to make a random password that doesn't start with "-", "_", or "0"?

function randomPassword() {
let length = 15,
password = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_",
space = "";
for (let i = 0, mu = password.length; i < length; ++i) {
space += password.charAt(Math.random() * mu)
}
return space;
}
console.log(randomPassword());
I'm new at javascript. I finally made this code but i don't want it to create a password that starts with "-", "_", "0". How can i do that?
We keep the _, - and 0 away from the character string while we generate the first character for the password. After generating the first character, we add the _, - and 0 back to the character string and generate the rest of the characters for the password.
function randomPassword() {
let length = 15;
// Initial characters without -, _ or 0
let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
// Generate first character
let password = characters.charAt(Math.floor(Math.random() * characters.length + 1));
// Add the symbols now
characters += "-_0";
let n = characters.length;
// Generate rest
for (let i = 0; i < length - 1; i++) {
password += characters.charAt(Math.floor(Math.random() * n));
}
// Return
return password;
}
console.log(randomPassword());
Another approach can be something like this :
function generatePassword() {
var length = 15,
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_",
retVal = "";
for (var i = 0, n = charset.length; i < length; ++i) {
let charOne = charset.charAt(Math.floor(Math.random() * n));
if (i == 0) {
while (charOne == "-" || charOne == "_" || charOne == "0")
charOne = charset.charAt(Math.floor(Math.random() * n));
}
retVal += charOne
}
return retVal;
}
console.log(generatePassword())
https://jsfiddle.net/40fa5neo/

How to encode letter from string into numbers

what I am trying to do is encode numbers in a string into numbers acording to the alphabet an leave the numbers still. so "abc123" would be "123123". Found the solution in javascript but cannot seem to fit into java. any help would be great, thanks.
The java function would be something like
import java.util.*;
import java.io.*;
class Main {
public static String NumberEncoding(String str) {
***call javascript function or translate it into java
}
public static void main (String[] args) {
// keep this function call here
Scanner s = new Scanner(System.in);
System.out.print(NumberEncoding(s.nextLine()));
}
}
The jasvascript function is
function NumberEncoding(str) {
str = str.toLowerCase();
var obj = {};
var alpha = "abcdefghijklmnopqrstuvwxyz";
var result = "";
for (var i = 1; i <= alpha.length; i++) {
obj[alpha[i-1]] = i;
}
for (var j = 0; j < str.length; j++) {
if (str[j].match(/[a-z]/)) {
result += obj[str[j]];
} else {
result += str[j];
}
}
return result;
}
Step one, create a variable to accumulate the String result; I would use a StringBuilder. Step two, iterate the input String one character at a time. Step three, convert that character to lower-case. Step four, check that the character is not a digit. Step five, if the character is a digit pass it through unchanged otherwise the value is easy to determine because Java characters are an integral type (e.g. 'a' + 1 = 'b' and 'b' - 1 = 'a'). Step six, return the result as a String. Finally, Java naming convention is camel case (starting with a lower case letter). Like,
public static String encodeNumber(String str) {
StringBuilder result = new StringBuilder();
for (int j = 0; j < str.length(); j++) {
char c = Character.toLowerCase(str.charAt(j));
if (c < 'a' || c > 'z') {
result.append(c);
} else {
result.append(1 + c - 'a');
}
}
return result.toString();
}
But, if you really wanted to, you can indeed directly call the JavaScript function from Java using Nashorn. Like,
String f = "function NumberEncoding(str) { str = str.toLowerCase();\n"
+ "var obj = {};\n"
+ "var alpha = \"abcdefghijklmnopqrstuvwxyz\";\n"
+ "var result = \"\";\n"
+ "for (var i = 1; i <= alpha.length; i++) {\n"
+ " obj[alpha[i-1]] = i;\n" + "}\n" + "\n"
+ "for (var j = 0; j < str.length; j++) {\n"
+ " if (str[j].match(/[a-z]/)) {\n"
+ " result += obj[str[j]];\n"
+ " } else {\n" + " result += str[j];" + " }\n" + "}\n"
+ "return result;\n" + "}";
ScriptEngine se = new ScriptEngineManager().getEngineByName("js");
try {
se.eval(f);
Invocable invocable = (Invocable) se;
Object result = invocable.invokeFunction("NumberEncoding", "zabc123");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
For the same result.
One way to do it is to use StringBuilder.
List<String> strings = Arrays.asList("abc123", "e2f3g4");
for (String s : strings) {
StringBuilder sb = new StringBuilder(s);
for (int i = 0; i < sb.length(); i++) {
char c = sb.charAt(i);
if (Character.isAlphabetic(c)) {
sb.replace(i, i + 1, Integer.toString(c - 'a' + 1));
}
}
System.out.println(sb.toString());
}
And the there's the Stream version.
List<String> strings = Arrays.asList("123abc", "e1f2g3", "xyz123");
List<String> converted = strings.stream().map(str -> str.chars().map(
chr -> Character.isAlphabetic(chr) ? chr - 'a' + 1
: chr - '0').mapToObj(String::valueOf).collect(
Collectors.joining())).collect(Collectors.toList());
System.out.println(converted);
Steps to solve it can be
Fill up an int[] of size, 26 (number of alphabets) with the values 1 to 26, corresponding to the position of letters in the alphabets.
Traverse through all characters of the input string and append its position from the int[] to a StringBuilder. If the character is not an alphabet, append it as it is.
Demo:
public class Main {
public static void main(String[] args) {
System.out.println(numberEncoding("abc123"));// Expected: 123123
}
static String numberEncoding(String str) {
str = str.toLowerCase();
String alpha = "abcdefghijklmnopqrstuvwxyz";
int[] obj = new int[alpha.length()];
StringBuilder result = new StringBuilder();
for (int i = 1; i <= obj.length; i++) {
obj[i - 1] = i;
}
for (int j = 0; j < str.length(); j++) {
if (str.charAt(j) >= 'a' && str.charAt(j) <= 'z') {
result.append(String.valueOf(obj[j]));
} else {
result.append(str.charAt(j));
}
}
return result.toString();
}
}
Output:
123123

How to find whether specific number of continuous consecutive numbers are contains in a string using javascript?

Suppose I want to know whether a string contains 5 or more continuous consecutive numbers.
var a = "ac39270982"; // False
var a = "000223344998"; // False
var a = "512345jj7"; // True - it contains 12345
var a = "aa456780"; // True - it contains 45678
Is there a RegEx available to accomplish this? Would it also be able to work in the following situation?
var a = "5111213141587"; // True
This should be true because it contains 11,12,13,14,15.
I'm not sure if it is possible to check the provided examples (single-digit, double-digit numbers) as well as larger numbers (triple-digit, etc.).
I took the time to make a 100% Javascript approach to your question. I made it to simply parse each character in the string and do integer only comparison. This works not only for five consecutive integers, but it works for checking for tenths as well (10's, 20's, etc). You can also increase/decrease the number of comparisons if you wish.
A fair warning: despite this method being potentially scalable if coded to look for all kinds of numeric sizes, you'd still be bound by computing power and number of comparisons. That is why I only provided the code for single digits and tenths, I leave it open to you/the community to decide how to expand from here.
jsFiddle
If you happen to need more details about how it works then let me know, I can further clarify its inner workings.
var str = "1111122asdgas222*&^%121314151617bdjfjahdi234bdce56789";
var consecutive = 5; // Number of comparisons
// Single digits
alert("It is " + consecutiveDigits(str, consecutive) + " that " + str + " contains " + consecutive + " consecutive digits.");
// Tenths digits
alert("It is " + consecutiveDigits(str, consecutive) + " that " + str + " contains " + consecutive + " consecutive tenths.");
function consecutiveDigits(str, consecutive){
var curr,
prev,
count = 0;
for(var i = 0; i < str.length; ++i) {
curr = parseInt(str.split('')[i]);
if(isNumeric(curr)) {
if(count === 0){
++count;
}
else if(prev + 1 === curr){
++count;
if(count === consecutive){
return true;
}
}
prev = curr;
}
}
return false;
}
function consecutiveTenths(str, consecutive, iterations){
var curr,
prev,
curr_tenth = 0,
prev_tenth = 0,
count = 0,
count_tenth = 0;
for(var i = 0; i < str.length; ++i) {
curr = parseInt(str.split('')[i]);
if(isNumeric(curr)) {
++count;
if(count === iterations){
curr_digit = (prev * 10) + curr;
alert(count_digit + " " + curr_digit + " " + prev_tenth);
if(count_digit === 0){
++count_digit;
}
else if(curr_tenth === (prev_tenth + 1)){
++count_digit;
if(count_digit === consecutive){
return true;
}
}
prev_digit = curr_digit;
count = 0;
}
else {
prev = curr;
}
}
else {
count = 0;
}
}
}
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
You can build regexp that will validate if it's true or not, but you might have a hard time retrieving the whole consecutive string. That said the RegExp will be a bit cumbersome, but you can create a function to create the regexp needed, depending on parameters wanted. See snippet:
function build_regexp(n) {
var string = "";
for (var i = 0; i <= 14 - n; i++) {
var start_num = i
for (var j = 0; j < n; j++) {
string += (start_num++).toString()
}
string += "|";
}
string = string.replace(/\|$/, '');
return string
}
document.getElementById('check').onclick = function() {
var regex = new RegExp(build_regexp(document.getElementById('cons').value), "g");
document.getElementById('regex').textContent = regex;
document.getElementById('result').innerHTML = (regex.exec(document.getElementById('to_check').value) || "false")
}
<div id="regex"></div>
<div>Enter wanted consecutive numbers: <input id="cons"></input></div>
<div>Enter string to check: <input id="to_check"></input></div>
<button id="check">check</button>
<div id="result"></div>
EDIT: Added a code snippet & fixed bug in numRegex
To answer the general case (i.e. contiguous sequence of arbitrary-length digits), you can do something like this:
http://jsfiddle.net/ksgLzL9u/8/
/* Find a sequence of n > 1 contiguously increasing integers in input
*
* If sequence is found, return an object:
* {
* start: <starting index of the sequence in input>,
* length: <length of the found sequence string>,
* first: <first number in the sequence>
* }
*
* Otherwise, return null
*/
function findSequence(input, n) {
var numRegex = /^(?:0|[1-9][0-9]*)$/;
// Try every starting position
for (var i = 0; i < input.length; ++i) {
// At the current starting position, try every length for the 1st number
for (var firstLen = 1; i + firstLen < input.length - 1; ++firstLen) {
var afterFirst = i + firstLen;
var first = input.slice(i, afterFirst);
// If the first string isn't an integer, move on
if (!numRegex.test(first)) {
continue;
}
// Convert the first string to an integer
var firstInt = parseInt(first, 10);
// Build what the rest of the string should look like following the
// first, in order to get a valid sequence
var rest = "";
for (var j = 1; j < n; ++j) {
rest = rest.concat(firstInt + j);
}
// Compare to what actually follows the starting string; if it
// matches, then we have our sequence; otherwise, continue on
if (input.slice(afterFirst, afterFirst + rest.length) === rest) {
return {
start: i,
length: first.length + rest.length,
first: first
};
}
}
}
return null;
}
$(function() {
function processChange() {
var input = $('#input').val();
var n = parseInt($('#n').val());
if (n > 1 && input.length) {
var result = findSequence(input, n);
if (result) {
$('#result').text(JSON.stringify(result, null, 2));
var afterFirst = result.start + result.first.length;
var afterSeq = result.start + result.length;
$('#highlighted').empty()
.append($('<span/>')
.text(input.slice(0, result.start)))
.append($('<span/>')
.addClass('sequence')
.append($('<span/>')
.addClass('first')
.text(result.first))
.append($('<span/>')
.text(input.slice(afterFirst, afterSeq))))
.append($('<span/>')
.text(input.slice(afterSeq)));
} else {
$('#result').text("No sequence found");
$('#highlighted').empty();
}
} else {
$('#result').text("");
$('#highlighted').empty();
}
}
$('input,n').on("keyup mouseup", processChange);
processChange();
});
#input {
width: 50%;
min-width: 200px;
}
#n {
width: 50px;
}
.highlighted-result {
font-family: monospace;
}
.highlighted-result .sequence {
background-color: yellow;
}
.highlighted-result .first {
border: solid black 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<h1>Input</h1>
<div>
<input id="input" type="text" value="111121314155" placeholder="input">
<input id="n" type="number" value="5" placeholder="n">
</div>
<h1>Results</h1>
<div id="highlighted" class="highlighted-result"></div>
<pre id="result"></pre>
I haven't attempted to optimize the solution (e.g. the firstLen iteration can be short-circuited, and the entire rest string doesn't need to be built up), but I left as-is to make the algorithm clearer.
function NstreamsOfNumberN (str) {
for (let i = 0; i < str.length; i++) {
let numBeingConsidered = Number(str[i]);
let numOfComparisonsToBeDone = numBeingConsidered - 1;
for (let j = i; j < numOfComparisonsToBeDone + i; j++) {
if (str[j] != str[j+1]) {break}//compare neigbourin nums
else if ((j - i + 1) === numOfComparisonsToBeDone)
{ let theNwithNstreams = numBeingConsidered
return [str, (theNwithNstreams), true]}
//(j - i + 1) equals num of comparisons that has been done.
}
}
return [str,null,false]
}
NstreamsOfNumberN('334775555583444582')
9 streams of the number 9
8 streams of the number 8
7 streams of the number 7 ...
3 streams of the number 3
2 streams of the number 2.
It is very difficult to do this with regex, but here is a tentative:
One digit
(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){4,}\d
https://regex101.com/r/mw4bvG/1
Two digits
(?:(\d)(?:0(?=(?:\1)1)|1(?=(?:\1)2)|2(?=(?:\1)3)|3(?=(?:\1)4)|4(?=(?:\1)5)|5(?=(?:\1)6)|6(?=(?:\1)7)|7(?=(?:\1)8)|8(?=(?:\1)9))|09(?=10)|19(?=20)|29(?=30)|39(?=40)|49(?=50)|59(?=60)|69(?=70)|79(?=80)|89(?=90)){4,}\d{2}
https://regex101.com/r/Kcl9FC/1
Three digits
(?:(\d{2})(?:0(?=(?:\1)1)|1(?=(?:\1)2)|2(?=(?:\1)3)|3(?=(?:\1)4)|4(?=(?:\1)5)|5(?=(?:\1)6)|6(?=(?:\1)7)|7(?=(?:\1)8)|8(?=(?:\1)9))|(\d)(?:09(?=(?:\2)10)|19(?=(?:\2)20)|29(?=(?:\2)30)|39(?=(?:\2)40)|49(?=(?:\2)50)|59(?=(?:\2)60)|69(?=(?:\2)70)|79(?=(?:\2)80)|89(?=(?:\2)90))|099(?=100)|199(?=200)|299(?=300)|399(?=400)|499(?=500)|599(?=600)|699(?=700)|799(?=800)|899(?=900)){4,}\d{3}
https://regex101.com/r/joeWdR/1
All together
(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){4,}\d|(?:(\d)(?:0(?=(?:\1)1)|1(?=(?:\1)2)|2(?=(?:\1)3)|3(?=(?:\1)4)|4(?=(?:\1)5)|5(?=(?:\1)6)|6(?=(?:\1)7)|7(?=(?:\1)8)|8(?=(?:\1)9))|09(?=10)|19(?=20)|29(?=30)|39(?=40)|49(?=50)|59(?=60)|69(?=70)|79(?=80)|89(?=90)){4,}\d{2}|(?:(\d{2})(?:0(?=(?:\2)1)|1(?=(?:\2)2)|2(?=(?:\2)3)|3(?=(?:\2)4)|4(?=(?:\2)5)|5(?=(?:\2)6)|6(?=(?:\2)7)|7(?=(?:\2)8)|8(?=(?:\2)9))|(\d)(?:09(?=(?:\3)10)|19(?=(?:\3)20)|29(?=(?:\3)30)|39(?=(?:\3)40)|49(?=(?:\3)50)|59(?=(?:\3)60)|69(?=(?:\3)70)|79(?=(?:\3)80)|89(?=(?:\3)90))|099(?=100)|199(?=200)|299(?=300)|399(?=400)|499(?=500)|599(?=600)|699(?=700)|799(?=800)|899(?=900)){4,}\d{3}
https://regex101.com/r/NyCLh6/1

Find the largest palindrome made from the product of two 3-digit numbers - Javascript

Can anyone tell me what's wrong with the code. Find the largest palindrome made from the product of two 3-digit numbers.
function largestPalindrome(){
for(var i =999; i>100; i--){
for(var j = 999; j>100; j--){
var mul = j*i;
if(isPalin(mul)){
return i * j;
}
}
}
}
function isPalin(i){
return i.toString() == i.toString().split("").reverse().join("");
}
console.log(largestPalindrome());
This answer was close to my question
but still i feel the way i am doing the loop it should return me the largest product.
Yours doesn't work properly since it checks 999*999, then 999*998, then 999*997 until it reaches about 999*583. While it doesn't check 997*995 or something closer to the top
which generates a larger number
function largestPalindrome(){
var arr = [];
for(var i =999; i>100; i--){
for(var j = 999; j>100; j--){
var mul = j*i;
if(isPalin(mul)){
arr.push(j * i);
}
}
}
return Math.max.apply(Math, arr);
}
function isPalin(i){
return i.toString() == i.toString().split("").reverse().join("");
}
console.log(largestPalindrome());
Here is another approach, store all palindrome generated by 3 numbers in an array, then use Math.max on the array to get the largest palindrome
I think if you apply maths to the problem you can decrease the guesswork really significantly.
I will write the three digit numbers as 1000 - a and 1000 - b which means the palindrome is 1 000 000 - 1000(a+b) + ab.
First, let's find solutions where ab < 1000. Then the three leftmost digits are 1000 - (a+b) and the three rightmost digits are ab.
Then I will say this is a palindrome with digits x,y,z:
100x+10y+z=ab
100z+10y+x=1000-a-b
thus
99x-99z = ab+a+b-1000
x-z = 1/99(ab+a+b-10)-10
So then (ab+a+b-10) is divisible by 99 and we also know that x and z being digits the left side is between -9 and 0 (the whole shebang is symmetrical so we can presume x <= z) so then 1/99(ab+a+b-10) is between 1 and 9. We can rewrite ab+a+b-10 as ab+a+b+1-11=99p so (a+1)(b+1)=99p+11=11*(9p+1) where p runs between 1 and 9. That's really easy:
for ($p = 1; $p <= 9; $p++) {
$n = 9 * $p + 1;
// This could be vastly optimized further.
for ($j = 1; $j <= $n; $j++) {
if ($n % $j === 0) {
$a = 1001 - $n / $j;
$b = 1001 - 11 * $j;
$test = $a * $b;
if (strrev($test) === (string) $test) {
print "$a $b " . $a * $b . "\n";
}
}
}
}
Now this prints only one solution which is the correct one.
Now we know 906609 is a solution so then is there a solution where ab > 1000 and 1000(a+b) - ab < 93391 ? There is not :)
As explained in #VisioN's comment:
995*583 = 580085 is a palindrome.
993*913 = 906609 is also a (larger) palindrome.
Your code checks 995*583 before 993*913 and exits at the first palindrome found, so it doesn't return the largest palindrome.
Solution: get the largest palindromes starting from 999*999 = 998001 downwards and check if they can be written as xyz*abc.
Or simply use the accepted solution from the question you linked :). Your solution, but instead of returning when you find the first palindrome, check if it is larger than the largest one already found, in which case you need to replace it. You can stop as soon as the largest palindrome is larger than i*999.
A bit more optimized version with comments included. Notice, there is no need of fast return, just store the max and optimize the cycles to not recalculate j*i if i*j has already been checked.
function largestPalindrome() {
var max = 0;
// not using i >= 100 since 100*100 is not palindrome! :)
for (var i = 999; i > 100; i--) {
// because i * j === j * i, no need of both i and j
// to count down from 999
for (var j = i; j > 100; j--) {
var mul = j * i;
if (isPalin(mul) && mul > max) {
max = i * j;
}
}
}
return max;
}
function isPalin(i) {
// adding empty string to i instead using of .toString
// avoids unnecessary wrapping in String object on the left side
i = '' + i;
// don't rely on ==, use === instead
return i === i.split("").reverse().join("");
}
console.log(largestPalindrome());
Suggesting a solution using underscore.js. First, find all palindromes and then loop through them starting from the largest one and return the one which has two 3-digit prime factors.
function isPalindrome(num) {
var str = num.toString();
return str.split('').reverse().join('') === str;
}
function palindromes() {
var max = 999 * 999;
var min = 100 * 100;
return _.select(_.range(max, min, -1), isPalindrome);
}
palindromes().find(function (x) {
if (_.find(_.range(999, 100, -1), function (y) {
return (x % y === 0 && y != x / y && x / y < 1000) ? true : false;
})) return true;
})
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int largestPalindrome()
{
int ret = 0;
for (int i = 999; i > 100; --i)
{
int jLimit = MAX(ret / i, 100);
for (int j = i; j > jLimit; --j)
{
int ans = i * j;
if (isPalin(ans))
{
ret = MAX(ans, ret);
}
}
}
return ret;
}
Reasons explained above.
We can recompute the range of j when we find a palindrome product.This should be faster.
The above solution will work perfectly fine but we will have issue ONLY when we try to find-out what are those 2 numbers (i = 913 and j = 993)
I will just modify the solution proposed by Azder
int max = 0;
int no1 = 0;
int no2 = 0;
// not using i >= 100 since 100*100 is not palindrome! :)
for (var i = 999; i > 100; i--) {
// because i * j === j * i, no need of both i and j
// to count down from 999
for (var j = i; j > 100; j--) {
var mul = j * i;
if (isPalin(mul)) {
if ((i+j) > max) {
max = i+j;
no1 = i; no2 = j;
}
}
}
}
//Now we can get the 2 numbers (no1=993 and no2=913)
return (no1*no2);
This is how I did it. I used the old fashioned way to check for a palindrome. It appears to run faster on my computer but I may be wrong. Pushing to an array, as in the above post, was definitely very slow on my computer. Noticeable lag at the console. I would recommend just checking to see if your product is greater than your current max, if it is, store that instead of pushing everything to an array. Please feel free to correct me if I'm wrong. Much appreciated.
//should find the largest palindrome made from the product of two 3 digit numbers
var largestPalindrome = function() {
var max = 0,
product = 0;
for (var num1 = 999; num1 >= 100; num1--) {
for (var num2 = 999; num2 >= 100; num2--) {
product = num1 * num2;
product > max && isPalindrome(product.toString()) ? max = product : 0;
}
}
return max;
};
//check to see if product is a palindrome
var isPalindrome = function(product) {
var palindromeCheck = true;
for (var i = 0; i < product.length / 2; i++) {
if (product[i] != product[product.length - i - 1])
palindromeCheck = false;
}
return palindromeCheck;
//return product === product.split("").reverse().join("");
};
I think you can go for code given at this link
http://www.mathblog.dk/project-euler-problem-4/
As this save your CPU cycle from multiplication, which is quite costly operation.
Well even in this you can make some more to make to make it more like, you can modify its while loop a bit
while (!found) {
firstHalf--;
palin = makePalindrome(firstHalf);
for (int i = 999; i > 99; i--) {
if ((palin / i) > 999 || i*i < palin) {
break;
}
if ((palin % i == 0)) {
found = true;
factors[0] = palin / i;
factors[1] = i;
break;
}
}
}
So here instead of moving from i=999 : 100, we can write it as i=sqrt(palin):100, as you can find factorial of number within its square root. Refer link How to find Number is prime number or not!
And also you can change if(condition) to if(!(palin%i)) as comparing with zero is usually not considered a good practice also comparing takes more CPU cycle compared to your simple negating bits.
instead of creating an Array or ArrayList to store all palindromes, I just created another variable max and stored highest valued palindrome in it.
My code is in Java, but you can understand the logic from it.
Here is my code to better explain what I said (read comments):
package euler;
import java.util.ArrayList; import java.util.Collections;
public class Problem4 {
public static void main (String[] args)
{
int product=0;
int max=0;
for(int i=999;i>100;i--)
{
for (int j=i;j>100;j--)
{
product=i*j;
if(isPalindrome(product))
{
//Just store maximum value of product.
//Following if loop is required in your code,in place of return i*j;
if(product>max)
{ max=product; }
}
}
}
System.out.println(max);
}
//might be inefficient to create StringBuilder and again String to compare.
public static boolean isPalindrome(int product)
{
boolean isPalindrome=false;
StringBuilder temp = new StringBuilder(Integer.toString(product)).reverse();
if(temp.toString().equals(Integer.toString(product)))
{
isPalindrome=true;
}
return isPalindrome;
}
}
What you are doing is returning and breaking out of the loop as soon as you get the first palindrome. Which in your case is not the maximum value palindrome.
Instead use an if condition and keep a track of maximum values and let the loop continue till end.
I have added the if condition that lets the loop running and registers the value.
Got the correct answer from this code.
PS. Thanks Xan for your input. I guess I could've explained it better first time.
I have seen a lot of posts for this question, this is the solution that i have come up with:
Smallest number that is multiple of two 3 digits number is 10000(100*100)
Largest number that is multiple of two 3 digits number is 998001(999*999)
Our palindrome lies between these two number, write a program to loop through these number and whenever you get a palindrome check whether its perfectly divisible by a 3 digit number and quotient is also a 3 digit number.
Below is my program in C#, the last number that it prints is our required answer, enjoy.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections;
namespace E
{
public class Program
{
public static void Main(string[] args)
{
//Your code goes here
for(int i=10000;i<=998001;i++)
{
string s1 = i.ToString();
char[] array = s1.ToCharArray();
Array.Reverse(array);
string s2 = new String(array);
if(s1==s2)
{
for(int j=100;j<=999;j++)
{
if(i%j==0 && i/j <= 999)
{
System.Console.WriteLine(i);
continue;
}
}
}
}
System.Console.WriteLine("done");
}
}
}
I believe this should be optimal
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;
template <typename T>
bool IsPalindrome(const T num) {
T reverse = 0;
T n = num;
while (n > 0) {
reverse = (reverse * 10) + n % 10;
n /= 10;
}
return reverse == num;
}
template <typename T = long long int>
T LongestPalindromeFromProductOfNDigitNums(int n) {
T result = 0, val = 0, max_n_digit_num = std::pow(10, n)-1,
least_n_digit_num = std::pow(10, n-1);
int n_checks = 0;
for (T i = max_n_digit_num; i >= least_n_digit_num; --i) {
if ((i*i) < result) {//found the highest palindrome
break;
}
for (T j = i; j >= least_n_digit_num; --j) {
val = i*j;
++n_checks;
if (val < result) // any product i*j for the value of 'j' after this will be less than result
break;
if (IsPalindrome(val)) {
if (val > result)
result = val;
break; // whenever a palindrome is found break since we only need highest one
}
}
}
std::cout << " Total num of checks = " << n_checks << std::endl;
return result;
}
int main() {
int n = 3;
std::cout << " LongestPalindromeFromProductOfNDigitNums for n = "
<< n << " is " << LongestPalindromeFromProductOfNDigitNums(n) << std::endl;
n = 4;
std::cout << " LongestPalindromeFromProductOfNDigitNums for n = "
<< n << " is " << LongestPalindromeFromProductOfNDigitNums(n) << std::endl;
return 0;
}
http://ideone.com/WoNSJP
Swift 3:
// my approach is to make 6-digit palindrome first and then
// check if I can divide it by 3-digit number
// (you can see some visual listing at the end of the code)
// execution time on my laptop is around: 2.75409698486328 sec
import Foundation
func maxPalindrom() -> Int {
var result = 999999
var i = 9
var j = 9
var k = 9
while true {
while true {
while true {
print("in K loop: \(result) k = \(k)")
if isDivisible(number: result) {
return result
}
if k <= 0 {
k = 9
result += 9900
break
}
result -= 1100
k -= 1
}
print("in J loop: \(result)")
if isDivisible(number: result) {
return result
}
if j < 0 {
j = 9
result += 90090
break
}
result -= 10010
j -= 1
}
print("in I loop: \(result)")
if isDivisible(number: result) {
return result
}
if i < 0 {
break
}
result -= 100001
i -= 1
}
if result == 100001 {
return -1
}
return -1
}
func isDivisible(number: Int) -> Bool {
var i = 999
while true {
if number % i == 0 && number / i < 999 {
return true
}
if i < 500 {
return false
}
i -= 1
}
}
let start = NSDate()
print(maxPalindrom()) // 906609
let end = NSDate()
print("executio time: \(end.timeIntervalSince(start as Date)) sec") // ~ execution time: 2.75409698486328 sec
//in K loop: 999999 k = 9
//in K loop: 998899 k = 8
//in K loop: 997799 k = 7
//in K loop: 996699 k = 6
//in K loop: 995599 k = 5
//in K loop: 994499 k = 4
//in K loop: 993399 k = 3
//in K loop: 992299 k = 2
//in K loop: 991199 k = 1
//in K loop: 990099 k = 0
//in J loop: 999999
//in K loop: 989989 k = 9
//in K loop: 988889 k = 8
//in K loop: 987789 k = 7
//in K loop: 986689 k = 6
//in K loop: 985589 k = 5
//in K loop: 984489 k = 4
//in K loop: 983389 k = 3
.....
Most of the answers here are correct. If you want to save going through 900*900 loops, you can just loop through all palindromes between 10000 and 998001 and find if they are divisible by 3 digit number.
static void largestpalindromeproduct(){
int a=999,b=999,c=a*b,loopcounter=0;
while(c>10000){
loopcounter++;
c--;
if(isPalindrome(c))
if(isDivisible(c))
break;
}
System.out.println(" largest : " + c+ "\nloops:"+ loopcounter);
}
static boolean isDivisible(int n){
int a=999;
while(a>=100){
if(n%a==0){
if(secondDividerIs3Digit(n,a))
return true;
}
a--;
}
return false;
}
static boolean secondDividerIs3Digit(int n, int a){
Integer b=n/a;
if(b.toString().length()==3)
return true;
return false;
}
static boolean isPalindrome(int n){
Integer i=new Integer(n);
String p=i.toString();
StringBuffer s=new StringBuffer(i.toString());
s.reverse();
if(p.equals(s.toString()))
return true;
return false;
}
As a very simple solution, this one works
public class LargestPallendrome {
public static void main(String[] args) {
int a = 999;
int b = 999;
long max = 0;
while (a > 100) {
long num = a * b;
if (checkPallendrome(num)) {
if (num > max)
max = num;
}
if (b >= 100)
b--;
else {
a--;
b = 999;
}
}
System.out.println(max);
}
public static boolean checkPallendrome(long num) {
String a = num + "";
String b = new StringBuffer(num + "").reverse().toString();
if (a.equals(b))
return true;
return false;
}
}
Another Simple Solution in JavaScript
function reverseNumber(n)
{
n = n + "";
return n.split("").reverse().join("");
}
function palindrom(){
var r= 1 , y =1;
var largest = 0;
while(r <= 1000){
var num1 = r;
var num2 = 0;
while(num1 <= 1000 && num2 <= num1){
product = num1 * num2;
if (product == reverseNumber(product)){
console.log(`${num1} x ${num2} = ${product}`);
if(product > largest){
largest = product;
}
}
num1 = num1 + 1;
num2= num2 + 1;
}
r++;
}
console.log(``)
console.log(`The largest is ${largest}`);
}
console.log(palindrom());
public static void main(String[] args) {
int tempAns = 0;
int max = 999;
for (int i = 100; i <= max; i++) {
for (int j = max; j >= i; j--) {
if (findPalindrome(i * j) && (i * j) > tempAns) {
System.out.println("Palindrome: " + j + " * " + i + " = " + j * i);
tempAns = i * j;
}
}
}
}
private static boolean findPalindrome(int n) {
String nString = String.valueOf(n);
int j = 0;
int stringLength = nString.length() - 1;
for (int i = stringLength; i >= 0; i--) {
if (nString.charAt(j) == nString.charAt(i)) {
if (i == 0) {
return true;
}
j++;
} else if (nString.charAt(j) != nString.charAt(i)) {
return false;
}
}
return false;
}
This is better because its using O(N) time complexity to find all the palindrome (As calculating palindrome of a six digit no is constant) and O(N2) nearly to find the actual palindrome that too worst case the moment its finding its first no we don't have to do any more calculation and here we are actually using the worst case on possible palindromic no. So I think its better
package ProjectEuler;
import java.util.ArrayList;
import java.util.Arrays;
public class Largest_Palindrome_Product {
public static void main(String[] args) {
int count=0;
for(int i=10000;i<998002;i++) {
int x=i,c=0;
while(x!=0) {
c=c*10+x%10;
x/=10;
}
if(c==i) {
count++;
}
}
int a[]=new int[count],count1=0;
for(int i=10000;i<998002;i++) {
int x=i,c=0;
while(x!=0) {
c=c*10+x%10;
x/=10;
}
if(c==i) {
a[count1]=i;
count1++;
}
}
Arrays.sort(a);
tp:for(int i=count-1;i>=0;i--)
{
for(int j=999;j>100;j--)
if(a[i]%j==0&&a[i]/j<=999) {
System.out.println(a[i]+" "+j+" "+a[i]/j);
break tp;
}
}
}
}
This is how I did it in Javascript. Simple & easy!
let num1 = 999;
let num2 = 999;
let arr = [];
function check(x, y)
{
if(String(x*y) == String(x*y).split("").reverse().join(""))
{
return true;
}
return false;
}
for(let i=0; i<999999; i++)
{
if(check(num1, num2))
{
arr.push(num1*num2);
num1--;
num2 = num1+1;
}
num2--;
}
console.log(arr.sort((x, y) => y-x)[0]);
I check it some times with random.randint. In python 3.7.1, you should run it with CMD and after 20 sec you will get the right answer.
import random
x,y,z,a,b=100,100,' ','',0
while 100<=x<=999 and 100<=y<=999:
a=x*y
x=random.randint(900,999)
y=random.randint(900,999)
print(x,' x ',y,'=')
z=len(str(a))
if z==6:
if str(a)[0] == str(a)[5]:
if str(a)[1] == str(a)[4]:
if str(a)[2] == str(a)[3]:
print(a,'yes')
exit(a)
else:
pass
#906609
Readable option:
function maxPalindrome(num) {
let maxPalindrome = 1;
for (let i = num; i > 0; i--) {
for (let j = num; j > 0; j--) {
const product = i * j;
if (
product.toString() === product.toString().split("").reverse().join("")
&& product > maxPalindrome
) {
maxPalindrome = product;
}
}
}
return maxPalindrome;
}
console.log(maxPalindrome(999));
This is how I have done with C#:
public static void maxPali() {
int max = 0;
for (int i = 99; i >= 10; i--) {
for (int j = 99; j >= 10; j--) {
if (i*j == reverse(i*j))
max = max >= (i*j) ? max : (i*j);
}
}
Console.WriteLine(max);
}
public static int reverse(int num) {
int rev = 0;
while (num > 0) {
int rem = num % 10;
rev = (rev * 10) + rem;
num /= 10;
}
return rev;
}
JavaScript solution:
(function main() {
let start = 100,
stop = 999,
step = 1;
let arr = Array(Math.ceil((stop + step - start) /
step)).fill(start).map((x, y) => x + y * step);
let max = 0;
arr.slice(0).reverse().map(function(i) {
arr.slice(0).reverse().map(function(j) {
if (i*j == (i*j).toString().split('').reverse().join(''))
if (max < (i*j))
max = i*j;
});
});
console.log(max); }());

Categories

Resources