Solving with only loop - c#

The number 124 has the property that it is the smallest number whose first three multiples contain the digit 2. Observe that
124*1 = 124, 124*2 = 248, 124*3 = 372 and that 124, 248 and 372 each contain the digit 2. It is possible to generalize this property to be the smallest number whose first n multiples each contain the digit 2. Write a function named smallest(n) that returns the smallest number whose first n multiples contain the digit 2. Hint: use modulo base 10 arithmetic to examine digits.
Its signature is
int smallest(int n)
Examples
If n is return because
4 624 because the first four multiples of 624 are 624, 1248, 1872, 2496 and they all contain the
digit 2. Furthermore 624 is the smallest number whose first four multiples contain the digit 2.
5 624 because the first five multiples of 624 are 624, 1248, 1872, 2496, 3120. Note that 624 is also
the smallest number whose first 4 multiples contain the digit 2.
6 642 because the first five multiples of 642 are 642, 1284, 1926, 2568, 3210, 3852
7 4062 because the first five multiples of 4062 are 4062, 8124, 12186, 16248, 20310, 24372, 28434.
Note that it is okay for one of the multiples to contain the digit 2 more than once (e.g., 24372).
I tried to solve this by this way
//Its a incomplete code
public static int smallest(int n)
{
int i = 1;
for (; ; )
{
int temp = 0;
int myNum = 0;
for (int j = 1; j <= n; j++)
{
myNum = i * j;
//check for condition
}
//if condition ture break
}
}
But I am stick to the problem is I cannot create hard coded n times variable.. Can you help me proceed that?
You may assume that such a number is computable on a 32 bit machine, i.e, you do not have to detect integer overflow in your answer.

using System;
using System.Collections.Generic;
namespace firstconsoleproject
{
class MainClass
{
public static void Main (string[] args)
{
int first=4;
int c=0;
int ax;
int ai;
Console.WriteLine ("please enter n");
ax = Convert.ToInt32( Console.ReadLine());
for (int i=11 ; ax>0 ;)
{ if (first==1)
{
c = ax+1;
i++;
}
c--;
ai=i*c;
for (int ten=10 ; ; )
{
if(ai%ten==2)
{
first=0;
break;
}else if (ai==0)
{
first=1;
break;
}
ai/=10;
}
if (c==0){Console.WriteLine("number is "+i);break;}
}Console.ReadKey ();
}
}
}

// Function smallest n
public int smallest(int a)
{
int temp = 0, holder = 0, k = 0;
if (a <= 0) return 0;
else
{
for (int i = 100; i < Int16.MaxValue; i++)
{
int count = 0;
k = 0;
int[] array = new int[a];
for (int j = 1; j < 9; j++)
{
holder = i * j;
temp = holder;
while (temp > 0)
{
int rem = temp % 10;
if (rem == 2)
{
count++;
if (k < a)
{
array[k] = j;
k++;
break;
}
}
temp /= 10;
}
if (count == a)
{
int countTemp = 0;
for (int h = 0; h < a; h++)
{
if (h + 1 < a)
{
if (array[h + 1] == array[h] + 1 && array[0] == 1 && array[h] > 0)
{
countTemp++;
if (countTemp == a - 1)
return i;
}
}
}
}
}
}
}
return 0;
}

public static int smallest(int n)
{
int i = 1;
for (; ; )
{
int contain = 0;
int temp = 0;
int myNum = 0;
for (int j = 1; j <= n; j++)
{
myNum = i * j;
temp = myNum;
while (true)
{
if (temp % 10 == 2)
{
contain++;
break;
}
temp = temp / 10;
if (temp <= 0)
break;
}
}
if (contain == n)
break;
i++;
}
return i;
}

Related

returns the smallest positive integer (greater than 0) that does not occur in Array

I have the following question:-
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
now i tried this code:-
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution
{
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
int n = 1;
Array.Sort(A);
for (int i = 1; i <= 100000; i++)
{
for (int i2 = 0; i2 <= A.Length - 1; i2++)
{
if (A[i2] == i)
{
n = A[i2] + 1;
break;
}
}
}
return n;
}
}
where my code worked well for these test data:-
A = [1, 2, 3]
A = [−1, −3]
while failed for this one:-
A = [1, 3, 6, 4, 1, 2] where it return 7 instead of 5.
any advice why my code failed on the 3rd test?
Thanks
using System.Linq;
int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();
I would use following approach that uses a HashSet<int> to check if a given integer is missing:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
A HashSet is a collection if unique values and it's very efficient in lookup items(complexity is O(1)). So you get a very readable and efficient algorithm at the cost of some memory.
Maybe you could optimize it by providing another algorithm in case the array is very large, you don't want to risk an OutOfMemoryException:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
if(A.Length > 1_000_000)
{
Array.Sort(A);
for (int i = rangeStart; i <= rangeEnd; i++)
{
int index = Array.BinarySearch(A, i);
if(index < 0) return i;
}
return null;
}
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
If you're allowed to sort the array in-place, which means modifying the input parameter value, here's a simple linear probe for the missing value (on top of the sort of course).
Here's the pseudo-code:
Sort the array
Skip all negatives and 0's at the start
Loopify the following:
Expect 1, if not found at current location return 1
Skip all 1's
Expect 2, if not found at current location return 2
Skip all 2's
Expect 3, if not found at current location return 3
Skip all 3's
... and so on for 4, 5, 6, etc. until end of array
If we get here, return currently expected value which should've been at the end
Here's the code:
public static int FirstMissingValue(int[] input)
{
Array.Sort(input);
int index = 0;
// Skip negatives
while (index < input.Length && input[index] < 1)
index++;
int expected = 1;
while (index < input.Length)
{
if (input[index] > expected)
return expected;
// Skip number and all duplicates
while (index < input.Length && input[index] == expected)
index++;
expected++;
}
return expected;
}
Test-cases:
Console.WriteLine(FirstMissingValue(new[] { 1, 3, 6, 4, 1, 2 }));
Console.WriteLine(FirstMissingValue(new[] { 1, 2, 3 }));
Console.WriteLine(FirstMissingValue(new[] { -1, -3 }));
output:
5
4
1
Your alg won't work in case input array becomes like this: [1,2-1,1,3,5]. I did this based on your alg. Give it a try:
int[] a = new int[] { -1, -2};
IEnumerable<int> uniqueItems = a.Distinct<int>().Where(x => x > 0);
if (uniqueItems.Count() == 0)
{
Console.WriteLine("result: 1");
}
else
{
Array asList = uniqueItems.ToArray();
Array.Sort(asList);
for (int i = 1; i <= 100000; i++)
{
if ((int)asList.GetValue(i - 1) != i)
{
Console.WriteLine("result: " + i);
break;
}
}
}
you can try like this.
public static int solution(int[] A)
{
int smallest = -1;
Array.Sort(A);
if(A[0] > 1)
return 1;
for(int i = 0; i < A.Length; i++)
{
if(A.Length != i+1 && A[i] + 1 != A[i + 1] && A[i+1] > 0)
{
smallest = A[i]+1;
break;
}
else if(A[i] > 0 && A.Length == i+1)
{
smallest = A[i] + 1;
}
}
return smallest > 0 ? smallest:1;
}
Here's the approach that uses O(N) partitioning followed by an O(N) search. This approach does not use any additional storage, but it DOES change the contents of the array.
This code was converted from here. Also see this article.
I've added comments to try to explain how the second stage findSmallestMissing() works. I've not commented the partitioning method, since that's just a variant of a standard partition as might be used in a QuickSort algorithm.
static class Program
{
public static void Main()
{
Console.WriteLine(FindSmallestMissing(1, 3, 6, 4, 1, 2));
Console.WriteLine(FindSmallestMissing(1, 2, 3));
Console.WriteLine(FindSmallestMissing(-1, -3));
}
public static int FindSmallestMissing(params int[] array)
{
return findSmallestMissing(array, partition(array));
}
// Places all the values > 0 before any values <= 0,
// and returns the index of the first value <= 0.
// The values are unordered.
static int partition(int[] arr)
{
void swap(int x, int y)
{
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
int pIndex = 0; // Index of pivot.
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > 0) // pivot is 0, hence "> 0"
swap(i, pIndex++);
}
return pIndex;
}
// This is the clever bit.
// We will use the +ve values in the array as flags to indicate that the number equal to that index is
// present in the array, by making the value negative if it is found in the array.
// This way we can store both the original number AND whether or not the number equal to that index is present
// in a single value.
//
// Given n numbers that are all > 0, find the smallest missing number as follows:
//
// For each array index i in (0..n):
// val = |arr[i]| - 1; // Subtract 1 so val will be between 0 and max +ve value in original array.
// if (val is in range) // If val beyond the end of the array we can ignore it
// and arr[val] is non-negative // If already negative, no need to make it negative.
// make arr[val] negative
//
// After that stage, we just need to find the first positive number in the array, which indicates that
// the number equal to that index + 1 is missing.
// n = number of values at the start of the array that are > 0
static int findSmallestMissing(int[] arr, int n)
{
for (int i = 0; i < n; i++)
{
int val = Math.Abs(arr[i]) - 1;
if (val < n && arr[val] >= 0)
arr[val] = -arr[val];
}
for (int i = 0; i < n; i++)
{
if (arr[i] > 0) // Missing number found.
return i + 1;
}
return n + 1; // No missing number found.
}
}
class Program
{
static void Main(string[] args)
{
int [] A = new int[] {1, 2, 3};
int n = 0;
bool found = false;
Array.Sort(A);
for (int i = 1; i <= 100000; i++) {
for (int x = 0; x <= A.Length - 1; x++) {
int next = (x + 1) < A.Length ? (x + 1): x;
if (A[x] > 0 && (A[next] - A[x]) > 0) {
n = A[x] + 1;
found = true;
break;
}
}
if(found) {
break;
}
}
Console.WriteLine("Smallest number: " + n);
}
}
int smallestNumber=Enumerable.Range(1,(int.Parse(A.Length.ToString())+1)).Except(A).Min();
Array.Sort(A);
for (int number = 1; number <= 100000; number++)
{
for (int num = number; i2 <= A.Length - 1; num++)
{
if (A[num] == number)
{
smallestNumber = A[num] + 1;
break;
}
}
}
return smallestNumber;
}
The easiest one :)
class Solution
{
public int solution(int[] array)
{
int[] onlyPositiveArray = array.Where(a => a > 0).OrderBy(a => a).Distinct().ToArray();
int smallestNumber = 1;
foreach (var number in onlyPositiveArray)
{
if (smallestNumber != number)
{
break;
}
smallestNumber ++;
}
if (!onlyPositiveArray.Contains(smallestNumber ))
{
return smallestNumber;
}
else
{
return smallestNumber + 1;
}
}
}
PHP Solution:
function solution($A) {
// write your code in PHP7.0
// sort array
sort($A);
// get the first
$smallest = $A[0];
// write while
while( in_array(($smallest),$A) || (($smallest) < 1 ) )
{
$smallest++;
}
return $smallest;
}
My solution, also if someone could test how performant it is?
public int solution(int[] N) {
if (N.Length == 0)
return 1;
else if (N.Length == 1)
return N[0] >= 0 ? N[0] + 1 : 1;
Array.Sort(N);
int min = Array.Find(N, IsUnderZero);
if (min ==
default)
return 1;
HashSet < int > hashSet = new HashSet < int > (N);
int max = N[N.Length - 1];
for (int i = min + 1; i <= max + 1; i++) {
if (!hashSet.Contains(i) && i > 0)
return i;
}
return max + 1;
bool IsUnderZero(int i) => i <= 0;
}
Try the below:
public static int MinIntegerGreaterThanZeroInArray(int[] A)
{
int minInt;
if (A.Length > 0)
{
Array.Sort(A);
for (minInt = 1; minInt <= A.Length; minInt++)
{
int index = Array.BinarySearch(A, minInt);
if (index < 0) return minInt;
}
return minInt;
}
//Array is empty.
throw new InvalidOperationException();
}
public static int Smallest(int[] A)
{
int maxPositiveInt = 1;
HashSet<int> NumDic = new HashSet<int>();
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(A[i]))
{
NumDic.Add(A[i]);
}
maxPositiveInt = Math.Max(A[i], maxPositiveInt);
}
//All numbers are negative
if (NumDic.Count == 0)
{
return 1;
}
int smallestinteger = 1;
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(smallestinteger))
{
return smallestinteger;
}
else
{
smallestinteger++;
}
}
return maxPositiveInt + 1;
}
static void Main(string[] args)
{
Console.WriteLine(solution(new int[]{1, 3, 6, 4, 1, 2}));
}
public static int solution(int[] A)
{
Array.Sort(A);
int smallest = A[0];
while (A.Contains(smallest+1)|| (smallest+1)<1)
{
smallest++;
}
return smallest +1;
}

How can I stop 0 from appearing in my array

So I have a method which returns an array of the factors of a number
Tools.cs
public static long[] GetFactors(long number)
{
long range = number / 2;
long potentialFactors = 2;
long[] factors = new long[range + 1];
factors[0] = 1;
factors[range] = number;
for (long i = 1; i < range; i++)
{
if (number % potentialFactors == 0)
{
factors[i] = potentialFactors;
potentialFactors++;
} else
{
potentialFactors++;
}
}
Console.WriteLine($"here are the factors for the number {number}:\n"+string.Join("\n", factors));
return factors;
}
program.cs
static void Main(string[] args)
{
Tools.GetFactors(24);
Console.ReadLine();
}
But when I run my code, this appears:
here are the factors for the number 24:
1
2
3
4
0
6
0
8
0
0
0
12
24
How can I stop 0 from appearing, should I rewrite the "for" loop, or is there a way to remove 0 from the array?
You are allocating a fixed size array and setting the element to non-zero only when it is a factor.
You should instead use a var factors = new List<long>(); and call factors.Add(potentialFactor); to only store those numbers which are valid factors.
This code is using List instead of Array and also there are some other changes.
public static List<long> GetFactors(long number)
{
long range = number / 2;
List<long> factors = new List<long>() { 1 };
for (long i = 2; i <= range; i++)
{
if (number % i == 0)
{
factors.Add(i);
}
}
factors.Add(number);
Console.WriteLine($"here are the factors for the number {number}:\n" + string.Join("\n", factors));
return factors;
}
I agree a list is better when you dont know before hand how many factors you will gote. But if you really want to use an Array. You can loop throught this array, find the 0's one by one and them swith Left the numbers. Like so :
// Extension Method of array
public static void RemoveAllZeros(this long[] array) // O(N^2)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] == 0)
{
// Grab the index override value and continue swift left
for (int j = i; j < array.Length - 1; j++)
{
array[j] = array[j + 1];
}
}
}
}
OR using a bit of LINQ and List :p :
// Extension Method of array
public static void RemoveAllZeros(this long[] numbers)
{
int zeroPst = numbers.ToList().IndexOf(0);
if (zeroPst == -1)
return;
for (int i = zeroPst; i < numbers.Length - 1; i++)
{
numbers[i] = numbers[i + 1];
}
numbers.RemoveAllZeros(); //Recursion, carefull
}

Digit difference sort

So I am trying to solve this task "Digit Difference Sort" on Codefights
Given an array of integers, sort its elements by the difference of their largest and smallest digits.
In the case of a tie, that with the larger index in the array should come first.
Example
For a = [152, 23, 7, 887, 243], the output should be digitDifferenceSort(a) = [7, 887, 23, 243, 152].
Here are the differences of all the numbers:
152: difference = 5 - 1 = 4;
23: difference = 3 - 2 = 1;
7: difference = 7 - 7 = 0;
887: difference = 8 - 7 = 1;
243: difference = 4 - 2 = 2.
23 and 887 have the same difference, but 887 goes after 23 in a, so in the sorted array it comes first.
I have an issue with two numbers having the same difference. Here's what I wrote so far:
int[] digitDifferenceSort(int[] a) {
return a.OrderBy(x => difference(x)).ToArray();
}
int difference(int x)
{
int min = 9, max = 0;
do
{
int tmp = x % 10;
min = Math.Min(min, tmp);
max = Math.Max(max, tmp);
} while ((x /= 10) > 0);
return max - min;
}
Didn't do much (for example the output is still [7, 23, 887, 243, 152] rather than [7, 887, 23, 243, 152])
How do I make element with larger index come first in result? What should I use instead of OrderBy?
I don't consider your difference method, i assume it works fine.
To your question: you have to keep revered order of the array (that the items with the same difference arrive will be sorted reverse). To do it, you could just reverse you input array: all items with not identical difference will be ordered correctly, and with the same differece will be ordered reversed:
int[] digitDifferenceSort(int[] a)
{
return a.Reverse().OrderBy(x => difference(x)).ToArray();
}
Following is my code for the above question digit difference sort. I am also getting output when running in Eclipse but when I paste the code on code signal it gives me a null pointer exception.
package NormalPrograms;
import java.util.ArrayList;
import java.util.Collections;
public class DigitDifferenceSort {
// For index wise sorting in descending order
public static int[] sortingnumberindexwise(int[] a, ArrayList<Integer> index) {
int k = 0;
int[] res = new int[index.size()];
int[] finalres = new int[index.size()];
for (int i = a.length - 1; i >= 0; i--) {
for (int j = 0; j < index.size(); j++) {
if (a[i] == (int) index.get(j)) {
res[k] = i;
index.remove(j);
k++;
break;
}
}
}
int g = 0;
k = 0;
for (int i = 0; i < res.length; i++) {
finalres[g] = a[res[k]];
g++;
k++;
}
return finalres;
}
public static int[] finddigitDifferenceandSort(int[] p) {
int[] finres = new int[p.length];
for (int i = 0; i < finres.length; i++) {
finres[i] = p[i];
}
// This finres array act as an temp array and reused to make final result array
int digit = 0;
ArrayList<Integer> A = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> B = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < 10; i++) {
B.add(new ArrayList<Integer>());
}
for (int i = 0; i < p.length; i++) {
int temp = 0;
temp = p[i];
while (p[i] > 0) {
digit = p[i] % 10;
p[i] /= 10;
A.add(digit);
}
int b = Collections.max(A);
int c = Collections.min(A);
int diff = b - c;
B.get(diff).add(temp);
A.clear();
}
for (int i = 0; i < B.size(); i++) {
if (B.get(i).size() > 1) {
ArrayList<Integer> C = new ArrayList<Integer>();
for (int k = 0; k < B.get(i).size(); k++) {
C.add(B.get(i).get(k));
}
B.get(i).clear();
for (int j : sortingnumberindexwise(finres, C)) {
B.get(i).add(j);
}
} else {
continue;
}
}
int k = 0;
for (int i = 0; i < B.size(); i++) {
for (int j = 0; j < B.get(i).size(); j++) {
if (B.get(i).size() == 0)
continue;
else {
finres[k] = B.get(i).get(j);
k++;
}
}
}
return finres;
}
public static void main(String[] args) {
int[] a = { 12, 21, 1, 1, 1, 2, 2, 3 };
for (int i : finddigitDifferenceandSort(a)) {
System.out.print(i + " ");
}
}
}

"myList.Count" is less then the amount of elements inside the list

I have a task to write a program that takes some numbers and step as input. Then it must make a sequence of binary representation of those numbers and destroy bits at positions 1, 1*step, 2*step, 3*step... Here is the code:
using System;
using System.Collections.Generic;
class BitKiller
{
static void Main()
{
int
amountNumbers = int.Parse(Console.ReadLine()),
step = int.Parse(Console.ReadLine()),
counter = 0,
number = 0
;
int[]
numBin= new int[8],
numbers = new int[amountNumbers]
;
var sequence = new List<int>();
for(int i = 0; i < amountNumbers; i++)
{
numbers[i] = int.Parse(Console.ReadLine());
numBin = ToBin(numbers[i]);
sequence.InsertRange(counter * 8, numBin);
foreach(int b in sequence)
{
Console.Write(b);
}
Console.WriteLine("");
counter++;
}
if(step == 1)
{
Console.WriteLine(0);
return;
}
for(int i = sequence.Count; i >= 0; i--)
{
if(i % step == 1)
{
sequence.RemoveAt(i);
}
}
Console.WriteLine("List count = {0}", sequence.Count);
if(sequence.Count % 8 != 0)
{
int padding = 8 - (sequence.Count % 8);
for(int i = 0; i < padding; i++)
{
sequence.Add(0);
}
}
foreach(int b in sequence)
{
Console.Write(b);
}
Console.WriteLine("");
for(int i = 7, power = 0, y = 0; y < sequence.Count; i--, y++, power++)
{
number = number + (sequence[i]) * ToPower(2, power);
if(i == 0)
{
Console.WriteLine("Result = {0}", number);
sequence.RemoveRange(0, 8);
foreach(int b in sequence)
{
Console.Write(b);
}
Console.WriteLine("");
number = 0;
i = 7;
y = 0;
power = 0;
}
}
}
static int[] ToBin(int number)
{
var binSequence = new int[8];
for(int i = 7; i >= 0; number /= 2, i--)
{
if(number % 2 == 0 || (number == 0 && i >= 0))
{
binSequence[i] = 0;
}
else
{
binSequence[i] = 1;
}
}
return binSequence;
}
static int ToPower(int number, int power)
{
int numberReturn = number;
if(power == 0)
{
return 1;
}
if(number == 1)
{
return number;
}
for(int i = 0; i < power - 1; i++)
{
numberReturn = numberReturn * number;
}
return numberReturn;
}
}
Now, there are a couple of extra print lines so you can see the binary numbers coming up as you input numbers. In short my program converts the numbers to lists containing only '1' and '0' and then removes values from this list according to my formula. My main question is why is:
sequence.Count
returning 22, when there are obviously 24 '1's inside the list. Test it with the following input: 3,19,255,255,255. The Result will be: 255, 254, 252, while the correct output would be 255, 255, 252.
It is happening, because of this code:
if(sequence.Count % 8 != 0)
{
int padding = 8 - (sequence.Count % 8);
for(int i = 0; i < padding; i++)
{
sequence.Add(0);
}
}
Because the sequence.Count is 22 ( why? ) the condition is true and the following for loop is replacing my last two '1's with 2 zeros. Which is causing the wrong output. So back to the point. Why is sequence.Count equal to 22, when there are 24 '1's in the list.
Sorry, if it is a bit long and confusing, but I posted the whole code, because I have no idea what and how could be interfering to cause this issue.
You are removing two items from the list in this code:
for(int i = sequence.Count; i >= 0; i--)
{
if(i % step == 1)
{
sequence.RemoveAt(i);
}
}
With the example input you gave, sequence.RemoveAt is being called when i == 20 and when i == 1. There were 24 items, then you removed 2 of them.
Duly noted: A whole day into programming affects my basic calculus. The list count and if conditions are both performing properly. After another hour of testing I realized that the problem was that I need to set both 'y' and 'i' to - 1 value, because they are incrementing instantly by 1 when they hit the for loop. Thanks for the tips.

Latest Codility Time Problems

Just got done with the latest Codility, passed it, but didnt get 100% on it
Here is the spec
A prefix of a string S is any leading contiguous part of S. For example, "c" and "cod" are prefixes of the string "codility". For simplicity, we require prefixes to be non-empty.
The product of prefix P of string S is the number of occurrences of P multiplied by the length of P. More precisely, if prefix P consists of K characters and P occurs exactly T times in S, then the product equals K * T.
For example, S = "abababa" has the following prefixes:
"a", whose product equals 1 * 4 = 4,
"ab", whose product equals 2 * 3 = 6,
"aba", whose product equals 3 * 3 = 9,
"abab", whose product equals 4 * 2 = 8,
"ababa", whose product equals 5 * 2 = 10,
"ababab", whose product equals 6 * 1 = 6,
"abababa", whose product equals 7 * 1 = 7.
The longest prefix is identical to the original string. The goal is to choose such a prefix as maximizes the value of the product. In above example the maximal product is 10.
In this problem we consider only strings that consist of lower-case English letters (a−z).
So basically, it is a string traverse problem. I was able to pass all the validation parts, but I lost on the time. Here is what I wrote
int Solution(string S)
{
int finalCount = 0;
for (int i = 0; i <= S.Length - 1; i++)
{
string prefix = S.Substring(0, i + 1);
int count = 0;
for (int j = 0; j <= S.Length - 1; j++)
{
if (prefix.Length + j <= S.Length)
{
string newStr = S.Substring(j, prefix.Length);
if (newStr == prefix)
{
count++;
}
}
if (j == S.Length - 1)
{
int product = count * prefix.Length;
if (product > finalCount)
{
finalCount = product;
}
}
}
}
return finalCount;
}
I know that the nested loop is killing me, but I cannot think of a way to traverse the "sections" of the string without adding the other loop.
Any help would be appreciated.
Naive brute-force solution takes O(N ** 3) time. Choose length from 1 to N, get a prefix of its length and count occurences by brute-force searching. Сhoosing length takes O(N) time and brute force takes O(N ** 2) time, totally O(N ** 3).
If you use KMP or Z-algo, you can find occurences in O(N) time, so the whole solution will be O(N ** 2) time.
And you can precalc occurences, so it will take O(N) + O(N) = O(N) time solution.
vector<int> z_function(string &S); //z-function, z[0] = S.length()
vector<int> z = z_function(S);
//cnt[i] - count of i-length prefix occurrences of S
for (int i = 0; i < n; ++i)
++cnt[z[i]];
//if cnt[i] is in S, cnt[i - 1] will be in S
int previous = 0;
for (int i = n; i > 0; --i) {
cnt[i] += previous;
previous = cnt[i];
}
Here's the blog post, explaining all O(N ** 3), O(N ** 2), O(N) solutions.
my effort was as follows trying to eliminate unnecessary string compares, i read isaacs blog but it is in c how would this translate to c#, i even went as far as using arrays everywhere to avoid the string immutability factor but there was no improvement
int Rtn = 0;
int len = S.Length;
if (len > 1000000000)
return 1000000000;
for (int i = 1; i <= len; i++)
{
string tofind = S.Substring(0, i);
int tofindlen = tofind.Length;
int occurencies = 0;
for (int ii = 0; ii < len; ii++)
{
int found = FastIndexOf(S, tofind.ToCharArray(), ii);
if (found != -1)
{
if ((found == 0 && tofindlen != 1) || (found >= 0))
{
ii = found;
}
++occurencies ;
}
}
if (occurencies > 0)
{
int total = occurencies * tofindlen;
if (total > Rtn)
{
Rtn = total;
}
}
}
return Rtn;
}
static int FastIndexOf(string source, char[] pattern, int start)
{
if (pattern.Length == 0) return 0;
if (pattern.Length == 1) return source.IndexOf(pattern[0], start);
bool found;
int limit = source.Length - pattern.Length + 1 - start;
if (limit < 1) return -1;
char c0 = pattern[0];
char c1 = pattern[1];
// Find the first occurrence of the first character
int first = source.IndexOf(c0, start, limit);
while ((first != -1) && (first + pattern.Length <= source.Length))
{
if (source[first + 1] != c1)
{
first = source.IndexOf(c0, ++first);
continue;
}
found = true;
for (int j = 2; j < pattern.Length; j++)
if (source[first + j] != pattern[j])
{
found = false;
break;
}
if (found) return first;
first = source.IndexOf(c0, ++first);
}
return -1;
}
I only got a 43... I like my code though! Same script in javascript got 56 for what it's worth.
using System;
class Solution
{
public int solution(string S)
{
int highestCount = 0;
for (var i = S.Length; i > 0; i--)
{
int occurs = 0;
string prefix = S.Substring(0, i);
int tempIndex = S.IndexOf(prefix) + 1;
string tempString = S;
while (tempIndex > 0)
{
tempString = tempString.Substring(tempIndex);
tempIndex = tempString.IndexOf(prefix);
tempIndex++;
occurs++;
}
int product = occurs * prefix.Length;
if ((product) > highestCount)
{
if (highestCount > 1000000000)
return 1000000000;
highestCount = product;
}
}
return highestCount;
}
}
This works better
private int MaxiumValueOfProduct(string input)
{
var positions = new List<int>();
int max = 0;
for (int i = 1; i <= input.Length; i++)
{
var subString = input.Substring(0, i);
int position = 0;
while ((position < input.Length) &&
(position = input.IndexOf(subString, position, StringComparison.OrdinalIgnoreCase)) != -1)
{
positions.Add(position);
++position;
}
var currentMax = subString.Length * positions.Count;
if (currentMax > max) max = currentMax;
positions.Clear();
}
return max;
}

Categories

Resources