I am trying to write a program that replaces even numbers with the word "EVEN". So far, I have:
List<int> num = new List<int>();
for (int num1 = 0; num < 101; num++)
{
num.add(num1)
}
foreach(int n in num1)
{
if (n/3)
{
num.Replace("EVEN")
}
}
Is this close or am I far off?
var list = new List<string>();
for (int i = 0; i < 101; i++)
{
string value = (i % 2 == 0) ? "EVEN" : i.ToString();
list.Add(value);
}
In one line:
var list = Enumerable.Range(1, 100).Select(i => (i % 2 == 0) ? "EVEN" : i.ToString()).ToList();
not sure why you are trying to do this, but this should work..:
var num = new List<string>();
for (int n = 0; n < 101; n++)
{
num.Add(n % 2 == 0 ? "EVEN" : n.ToString());
}
Solutions have been provided for constructing a list of strings where each element of the list will be the number if it's odd or "EVEN" if it's even.
If, for some reason, you actually need to take an existing list of int and perform such a replacement, make sure you understand a fundamental problem: You can't insert the string "EVEN" into a strongly-typed list of int.
If you do start with a List<int>, you'll have to iterate over it and insert the results into a new List<string>, replacing even numbers with "EVEN" as per #CMP or #Can Gencer's answers.
Enumerable.Range(1, 100)
.Select(n => (n % 2) == 0 ? "EVEN" : n.ToString())
.ToList();
The list of numbers probably should be string if you want to replace with "even".
List<string> numbers = new List<string>();
numbers.Add("1");
numbers.Add("2");
numbers.Add("3");
for (int i = 0; i < numbers.Count; i++)
{
int n = 0;
bool success = int.TryParse(numbers[i], out n);
if (success && n % 2 == 0)
{
numbers[i] = "Even";
}
}
//Output Test Results
foreach (string number in numbers)
{
Console.WriteLine(number);
}
Related
I want to check how many specific digits appear in an array of numbers. For example, digit 2 appears:
input from 1 to 20
output
3 times
another example:
input from 1 to 100
output
19 times
this is my code
int count = 0;
string x = "";
string y = "";
string[] arr2 = new string[100000000];
for (int i = 1; i < arr2.Length; i++)
{
arr2[i - 1] = i.ToString();
}
foreach (var item in arr2)
{
for (int digit = 0;digit<item.Length;digit++)
{
if (digit == 2)
count++;
}
}
Console.WriteLine(count);
My code doesn't work but i don't know where the problem is.
Note : This must be done with for / foreach loops only, not using Dictionary or LINQ or DivRem.
An efficient and concise method is to use Aggregate to sum the counts as you go, rather than counting then summing or similar (this approach only requires one pass through the array):
arr2.Aggregate(0, (total, s) => total + s.Count(c => c == '2'))
This is functionally equivalent to:
int total = 0;
foreach (string s in arr2)
total += s.Count(c => c == '2');
If you don't want to use Linq or extension methods, then you can take the above code and just expand the remaining extension method:
int total = 0;
foreach (string s in arr2)
{
foreach (char c in s)
{
if (c == '2')
total++;
}
}
Note that converting your numbers to strings before processing them is a bit wasteful - you can do this using the modulus and division operators % and / to inspect the digits directly (note that this code requires a minor tweak to work with negative numbers):
int total = 0;
foreach (int i in somearrayofnumbers)
{
while (i != 0)
{
if (i % 10 == 2)
total++;
i /= 10;
}
}
Alright, for the sake of completion - the nicest way I can think of to do this is a hybrid of the above:
int CountDigits(int in, int val)
{
int total = 0;
while (in != 0)
{
if (in % 10 == val)
total++;
in /= 10;
}
return total;
}
...
int digitCount = numbers.Aggregate((total, i) => total + CountDigits(i, 2));
Using Math.DivRem is pretty unreadable, hence sticking to % and / above.
If you want to just use loops without the string array:
long count =0;
string x = "";
string y = "";
foreach (var i in Enumerable.Range(1, 100000000))
{
var s = i.ToString();
foreach (char t in s)
{
if (t == '2')
count++;
}
}
Console.WriteLine(count);
If you want to just use loops and the string array:
long count = 0;
string x = "";
string y = "";
string[] arr2 = new string[100000000];
for (var i = 1; i <= arr2.Length; i++)
{
arr2[i - 1] = i.ToString();
}
for (var i = 0; i < arr2.Length; i++)
{
var s = arr2[i];
if (s == null)
continue;
for (var j = 0; j < s.Length; j++)
{
if (s[j] == '2')
count++;
}
}
Console.WriteLine(count);
If you are willing to use LINQ
Either of these solutions will work. The latter will likely be more efficient.
var count = string.Join("", arr2).LongCount(z => z == '2');
var count = arr2.Select(z => z.LongCount(y => y == '2')).Sum();
The former joins all the values into a huge string, and then counts all the 2s in it.
The latter counts the number of 2s in each individual string and then adds them up at the end.
I have a program that creates a given number of folders named from a text file. I have the following algorithm:
private void button2_Click(object sender, EventArgs e)
{
if (path != null && Directory.Exists(path))
{
Random rnd = new Random();
for (int i = 0; i < value; i++)
{
var lines = File.ReadAllLines(path1);
var randomLineNumber = rnd.Next(0, lines.Length);
var line = lines[randomLineNumber];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 2 == 1)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, line));
}
}
}
I have a text file with one word on each line. My algorithm should take a random word from it and rename the folders that I create following the next rule:
lldlldll...ll and so on, where:
l - letter (upper case or lower case - it should be random)
d - digit
Real example:
Number of folders: 13
My list:
computer
explore
wireless
dog
love
electrical
phone
alex
andrew
elevator
door
Desired output:
aN5dR0ew7
dO1G6
DO3oR5
CO4mP7uT6er8
pH6ON1e
al9EX5
eX0pl9Or4e
EL5eC0Tr8iC0aL7
lO4vE2
wi1re9le6Ss47
el3eV0AT8oR9
Actual output:
aN5dR0ew7
dO1G6
DO3oR5
DO4G7
DO6g1
Do9G1
eL4Ec6TR5Ic3Al9
EL5eC0Tr8iC0aL7
eX2Pl6OR7E8
wi1re9le6Ss47
Wi8Re7Le6ss54
The problem is the next one:
If I create 20 folders and I also have 20 words in that .txt file, the algorithm will not use all of the words but just some of them ( and it will repeat them 3 times). The digits are ok / the upper-lower letters are ok. I just have to be sure that each word from that txt will be used.
Any help please ?
There is no guarantee that a Random() instance will generate different values each time its Next method is called. 9 (nine) is a perfectly good random number, and it could be all you'll receive until the end of time.
What you want is the Fisher–Yates shuffle algorithm... You shuffle the lines of the txt file and so you guarantee that all the lines are used, and each line is only used once. If you need more lines than the file has, every time you have used all the lines of the file you re-shuffle it and restart.
This should be the full solution:
Random rnd = new Random();
var lines = File.ReadAllLines(path1);
for (int i = 0; i < value; i++)
{
if (i % lines.Length == 0)
{
// We after using all the rows once
// we used all of them (or at the beginning)
// Shuffle, Fischer-Yates
int n = lines.Length;
while (n > 1)
{
n--;
int k = rnd.Next(n + 1);
string value2 = lines[k];
lines[k] = lines[n];
lines[n] = value2;
}
}
var line = lines[i % lines.Length];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 2 == 1)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, line));
}
I would create a list of integers right after this row
var lines = File.ReadAllLines(path1);
List<int> list = Enumerable.Range(0, lines.Length).ToList<int>();
Shuffle the list: Randomize a List<T>
and loop trought shuffled lines
for (int i = 0; i < list.Count; i++) {
var lineItem = lines[i];
}
I have this array of integers:-
int[] numbers = new int[] { 10, 20, 30, 40 };
I am trying to create an array which will have first element, last element, second element, second-last element and so on..
So, my resulting output will be:-
int[] result = {10,40,20,30};
This was my approach, in one loop start from first and go till the middle & in second loop start from last and get to the middle and select items accordingly, but I totally messed it up. Here is my attempted code:-
private static IEnumerable<int> OrderedArray(int[] numbers)
{
bool takeFirst = true;
if (takeFirst)
{
takeFirst = false;
for (int i = 0; i < numbers.Length / 2; i++)
{
yield return numbers[i];
}
}
else
{
takeFirst = true;
for (int j = numbers.Length; j < numbers.Length / 2; j--)
{
yield return numbers[j];
}
}
}
Need Help.
You might try this:
int[] result = numbers.Zip(numbers.Reverse(), (n1,n2) => new[] {n1, n2})
.SelectMany(x =>x)
.Take(numbers.Length)
.ToArray();
Explanation: This approach basically pairs up the elements of the original collection with the elements of its reverse ordered collection (using Zip). So you get a collection of pairs like [first, last], [second, second from last], etc.
It then flattens those collection of pairs into a single collection (using SelectMany). So the collection becomes [first, last, second, second from last,...].
Finally, we limit the number of elements to the length of the original array (n). Since we are iterating through twice as many elements (normal and reverse), it works out that iterating through n elements allow us to stop in the middle of the collection.
As a different approach, this is a modification on your existing method:
private static IEnumerable<int> OrderedArray(int[] numbers)
{
var count = (numbers.Length + 1) / 2;
for (int i = 0; i < count; i++)
{
yield return numbers[i];
int reverseIdx = numbers.Length - 1 - i;
if(i != reverseIdx)
yield return numbers[reverseIdx];
}
}
ok,
public static class Extensions
{
public static IEnumerable<T> EndToEnd<T>(this IReadOnlyList<T> source)
{
var length = source.Count;
var limit = length / 2;
for (var i = 0; i < limit; i++)
{
yield return source[i];
yield return source[length - i - 1];
}
if (length % 2 > 0)
{
yield return source[limit];
}
}
}
Which you could use like this,
var result = numbers.EndToEnd().ToArray();
more optimally,
public static class Extensions
{
public static IEnumerable<T> EndToEnd<T>(this IReadOnlyList<T> source)
{
var c = source.Count;
for (int i = 0, f = 0, l = c - 1; i < c; i++, f++, l--)
{
yield return source[f];
if (++i == c)
{
break;
}
yield return source[l];
}
}
}
no divide or modulus required.
With a simple for;
int len = numbers.Length;
int[] result = new int[len];
for (int i = 0, f = 0, l = len - 1; i < len; f++, l--)
{
result[i++] = numbers[f];
if (f != l)
result[i++] = numbers[l];
}
Based on Selman22's now deleted answer:
int[] numbers = new int[] { 10, 20, 30, 40 };
int[] result = numbers
.Select((x,idx) => idx % 2 == 0
? numbers[idx/2]
: numbers[numbers.Length - 1 -idx/2])
.ToArray();
result.Dump();
(The last line is LinqPad's way of outputting the results)
Or in less LINQy form as suggested by Jeppe Stig Nielsen
var result = new int[numbers.Length];
for (var idx = 0; idx < result.Length; idx++) {
result[idx] = idx % 2 == 0 ? numbers[idx/2] : numbers[numbers.Length - 1 -idx/2];
}
The principle is that you have two sequences, one for even elements (in the result) and one for odd. The even numbers count the first half of the array and the odds count the second half from the back.
The only modification to Selman's code is adding the /2 to the indexes to keep it counting one by one in the right half while the output index (which is what idx basically is in this case) counts on.
Came up with this
static void Main(string[] args)
{
List<int> numbers = new List<int>() { 10, 20, 30, 40, 50, 60, 70};
List<int> numbers2 = new List<int>();
int counter1 = 0;
int counter2 = numbers.Count - 1;
int remainder = numbers.Count % 2 == 0 ? 1: 0;
while (counter1-1 < counter2)
{
if (counter1 + counter2 % 2 == remainder)
{
numbers2.Add(numbers[counter1]);
counter1++;
}
else
{
numbers2.Add(numbers[counter2]);
counter2--;
}
}
string s = "";
for(int a = 0; a< numbers2.Count;a++)
s+=numbers2[a] + " ";
Console.Write(s);
Console.ReadLine();
}
This late answer steals a lot from the existing answers!
The idea is to allocate the entire result array at once (since its length is known). Then fill out all even-indexed members first, from one end of source. And finally fill out odd-numbered entries from the back end of source.
public static TElement[] EndToEnd<TElement>(this IReadOnlyList<TElement> source)
{
var count = source.Count;
var result = new TElement[count];
for (var i = 0; i < (count + 1) / 2; i++)
result[2 * i] = source[i];
for (var i = 1; i <= count / 2; i++)
result[2 * i - 1] = source[count - i];
return result;
}
Came up with this
public int[] OrderedArray(int[] numbers)
{
int[] final = new int[numbers.Length];
var limit=numbers.Length;
int last = numbers.Length - 1;
var finalCounter = 0;
for (int i = 0; finalCounter < numbers.Length; i++)
{
final[finalCounter] = numbers[i];
final[((finalCounter + 1) >= limit ? limit - 1 : (finalCounter + 1))] = numbers[last];
finalCounter += 2;
last--;
}
return final;
}
This logic is to find the number n in the array in which the range between n and n + 5 will include the most numbers in the array. I came up with a solution but it requires a nested loop, therefore it is kind of slow. Is there any way to improve its performance? Thanks in advance.
The array is guaranteed to sorted.
int[] myArray = new int[]{1,2,4,5,7,9,15,19};
int bestNumber = 0;
int MaxMatchFound = 0;
for (int o = 0; o < myArray.Length; o++)
{
int TempMatchFound = 0;
for (int i = 0; i < myArray.Length; i++)
{
if (myArray[i] >= myArray[o] && myArray[i] <= (myArray[o] + 5))
{
TempMatchFound++;
}
}
if (TempMatchFound > MaxMatchFound)
{
bestNumber = myArray[o];
MaxMatchFound = TempMatchFound;
}
}
return bestNumber;
Bucket the values, then loop over the values v and sum the associated counts for all values w that satisfy v <= w <= v + 5, then find the max count:
var buckets = myArray.GroupBy(n => n)
.ToDictionary(g => g.Key, g => g.Count());
var rangeCounts =
buckets.Keys
.Select(v =>
new {
Value = v,
Count = Enumerable.Range(0, 6)
.Sum(i => buckets.ContainsKey(v + i) ?
buckets[v + i] :
0
)
}
);
var bestRange = rangeCounts.MaxBy(x => x.Count);
Now, bestRange.Value is the starting point for your best range and bestRange.Count is the number of elements falling into the range [bestRange.Value, bestRange.Value + 5]. Here, I've used MaxBy.
Think this gets you linear performance. Building dictionary is linear, building rangeCounts is linear, MaxBy is linear. Even works on non-sorted.
Here you go: This runs in O(N) time, and O(1) memory. This forms the buckets described in other solutions, then discards them as you move through the array. The Queue is used to track which buckets are 'active' in the sense that they can be added to. The Dictionary will never have more than 6 entries in it, neither will the Queue.
int[] myArray = new int[]{1,2,4,5,7,9,15,19};
Dictionary<int, int> counts = new Dictionary<int, int>();
Queue<int> q = new Queue<int>();
int n = 0;
int currentMaxCount = 0;
for(int i = 0; i < myArray.Length; i++)
{
var currentNum = myArray[i];
if(counts.ContainsKey(currentNum))
{
counts[currentNum]++;
}
else
{
counts[currentNum] = 1;
q.Enqueue(currentNum);
}
for(int j = 1; j <= 5; j++)
{
if(counts.ContainsKey(currentNum - j))
counts[currentNum - j]++;
}
if(q.Peek() + 5 < currentNum)
{
if(counts[q.Peek()] > currentMaxCount)
{
currentMaxCount = counts[q.Peek()];
n = q.Peek();
}
counts.Remove(q.Dequeue());
}
}
while(q.Count > 0)
{
if(counts[q.Peek()] > currentMaxCount)
{
currentMaxCount = counts[q.Peek()];
n = q.Peek();
}
counts.Remove(q.Dequeue());
}
Console.WriteLine("There are {0} matches between {1} and {2}", currentMaxCount, n, n + 5);
Here's a solution that is O(n) and uses O(1) extra space regardless of the range.
It does a single pass through the array, always making 2N comparisons. I don't see any way to improve on this algorithm, although there are certainly micro optimizations that could squeeze a little more speed out of the implementation.
private int FindRange(int[] myArray)
{
const int range = 5;
int start = 0;
int maxMatchFound = 0;
int maxIndex = 0;
for (int i = 0; i < myArray.Length; ++i)
{
if (myArray[i] > myArray[start] + range)
{
int matchLength = i - start;
if (matchLength > maxMatchFound)
{
maxMatchFound = matchLength;
maxIndex = start;
}
// move forward until within range
do
{
++start;
} while (myArray[i] > myArray[start] + range);
}
}
// Final check, from myArray[start] to end of array
int len = myArray.Length - start;
if (len > maxMatchFound)
{
maxMatchFound = len;
maxIndex = start;
}
return maxIndex;
The idea here is that if a particular number a[x] falls within the range for a[i] then it will fall within the range for a[i+1], assuming that x > i. (So in your original array, the value at a[3] falls within the range of a[0], so it will also fall within the range of a[1] and a[2]).
So the index i is incremented until the value it references falls out of the range of a[start]. Then, start is incremented until a[i] is in range again. The two indexes move forward through the array in that alternating fashion.
Here's a one-line LINQ option. Not the best in terms of performance (it iterates multiple times). Still worth noting.
var result = myArray
.OrderByDescending(i => myArray.Count(i2 => i2 >= i && i2 <= i + 5))
.First();
I have an array with "n" numbers and I need to print all repeated numbers only one time
i made this code, but something is wrong
for (int i = 0; i < numbers.Length; i++)
{
for (int j = 1; j < numbers.Length; j++)
{
if (numbers[i] == numbers[j] && i!=j)
{
Console.WriteLine(numbers[i]);
break;
}
}
}
then if my array have the elements {2,3,1,5,2,3}
the program prints :
2
3
3
what can I do?
You can use:
using System.Linq;
…
foreach(var number in numbers.Distinct()) Console.WriteLine(number);
edit
I may have misunderstood the requirement. If you only want to output the numbers that appear more than once, then you can use:
foreach(var group in numbers.GroupBy(n => n).Where(g => g.Count() > 1))
Console.WriteLine(group.Key);
var query = numbers.GroupBy(x => x)
.Where(g => g.Skip(1).Any())
.Select(g => g.Key);
foreach (int n in query)
{
Console.WriteLine(n);
}
Or, alternatively...
var dict = new Dictionary<int, int>();
foreach (int n in numbers)
{
int count;
dict.TryGetValue(n, out count);
if (count == 1)
{
Console.WriteLine(n);
}
dict[n] = count + 1;
}
The problem in your code: you get 3 repeated because when i is 1 (looking at the first 3) there's another 3 in the list at the end, and when i is 5 (looking at the last 3) there's another three in the list near the beginning.
Instead you should look at only those numbers which come after your current position - change to int j = i; so that you only look at the positions after your current position, and you won't get repeated results.
for (int i = 0; i < numbers.Length; i++)
{
for (int j = i; j < numbers.Length; j++)
{
if (numbers[i] == numbers[j] && i!=j)
{
Console.WriteLine(numbers[i]);
break;
}
}
}
Having said that, your algorithm is not as efficient as using a built in algorithm. Try GroupBy
var duplicates = numbers.GroupBy(n => n)
.Where(group => group.Count() > 1);
foreach (var group in duplicates)
{
Console.WriteLine("{0} appears {1} times", group.Key, group.Count());
}
One way to get distinct numbers is
var uniqueNumbers = numbers.Distinct().ToArray()
and then iterate over uniqueNumbers like you have in your snippet with numbers.
You can add the number to a HashSet as you loop and then only print if not in hash set.
That allows you to do it in one pass.
The algorithm above is n^2 which should be avoided.
// deletes an integer if it appears double
#include <iostream.h>
#include <conio.h>
int main ()
{
int count=0;
int ar[10]={1,2,3,3,3,4,5,6,7,7};
for (int i=0; i<10; i++)
{
if (ar[i]==ar[i+1])
count++;
else
cout << ar[i];
}
getch();
return 0;
}