How to write a method using strand sort - c#

I admit, this is a homework for my project and i came here because i don't know how to do it.
What i have to do
Write a method editUsingStrands(), which returns the growing field of integers arranged. Returned field should be the same size and with the same values ​​as stored in the specified field. The algorithm should not exceed O (n3) growth of complexity.
I have done this using LIST, but i just found out is not allowed, and so are not any complex functions like Sort, RemoveAt, Count...(dunno if all are complex functions, but i know they are not allowed).
Can somebody help me re-create it without using LIST and those functions?
Thank you very much!
My code
static int[] editUsingStrands(int[] field)
{
List<int> organizedField = new List<int>();
List<int> xField = new List<int>(field);
while(xField.Count > 0)
{
List<int> sublist = new List<int>();
sublist.Add(xField[0]);
xField.RemoveAt(0);
for(int i=0; i< xField.Count; i++)
{
if(xField[i] > sublist[sublist.Count-1])
{
sublist.Add(xField[i]);
xField.RemoveAt(i);
i--;
}
}
organizedField = new List<int>(mergeTogether(organizedField.ToArray(), sublist.ToArray()));
}
return organizedField.ToArray();
}
static int[] mergeTogether(int[] field1, int[] field2)
{
List<int> organizedMergedField = new List<int>();
int counter1 = 0, counter2 = 0;
while ((counter1 + counter2) < (field1.Length + field.Length))
{
if (field1.Length > counter1)
{
if (field2.Length > counter2)
{
if (field1[counter1] < field2[counter2])
{
organizedMergedField.Add(field1[counter1]);
counter1++;
}
else
{
organizedMergedField.Add(field2[counter2]);
counter2++;
}
}
else
{
organizedMergedField.Add(field1[counter1]);
counter1++;
}
}
else
{
organizedMergedField.Add(field2[counter2]);
counter2++;
}
}
return organizedMergedField.ToArray();
}

Related

Large list size times out practice problem

I was working on a HackerRank practice problem and ran into a interesting error
when finished. This code works on every case except the ones causing it to fail
(and they are all timeout exceptions)
Practice Problem
The short version of the problem is you are given a leaderboard (int[]) and "alice's" scores (int[]) you have to find what place she got for each score in the leaderboard...View the link above for the whole problem.
My Solution
public static int[] climbingLeaderboard(int[] scores, int[] alice)
{
int[] results = new int[alice.Length]; //The array that stores alice's placements for each score
Dictionary<int, List<int>> scoresDict = new Dictionary<int, List<int>>(); //Key = x place (1st, 2nd, etc), the list is all the numbers that are at x place
for(int i = 0; i < alice.Length; i++)
{
List<int> alicePlace = scores.ToList<int>();
//Add the score to the array (converted to list for .Add)
alicePlace.Add(alice[i]);
//Sorts in reverse order to get the new score in the correct place
alicePlace = RecalculateScores(alicePlace);
//Breaks down the scores into the dictionary above
scoresDict = SeperateScores(alicePlace);
//Addes the place to the array
results[i] = GetPlace(scoresDict, alice[i]);
}
return results;
}
//Returns scores[] in reverse SORTED order
public static List<int> RecalculateScores(List<int> scores)
{
List<int> scoresRet = scores;
scoresRet.Sort();
scoresRet.Reverse();
return scoresRet;
}
//Gets the place (key) for where score is in the dict's value list
public static int GetPlace(Dictionary<int, List<int>> dict, int score)
{
foreach (int i in dict.Keys)
{
foreach (int ii in dict[i])
{
if (ii == score)
{
return i;
}
}
}
return -1;
}
//Seperates the array into a dictionary by score placement
public static Dictionary<int, List<int>> SeperateScores(List<int> scores)
{
int placeholder = scores[0];
int currentPlace = 1;
Dictionary<int, List<int>> scoresByPlace = new Dictionary<int, List<int>>();
for (int i = 0; i < scores.Count(); i++)
{
if (scores[i] == placeholder)
{
if (!scoresByPlace.Keys.Contains(currentPlace) || scoresByPlace[currentPlace] == null)
{
scoresByPlace[currentPlace] = new List<int>();
}
scoresByPlace[currentPlace].Add(scores[i]);
placeholder = scores[i];
}
else
{
currentPlace++;
if (!scoresByPlace.Keys.Contains(currentPlace) || scoresByPlace[currentPlace] == null)
{
scoresByPlace[currentPlace] = new List<int>();
}
scoresByPlace[currentPlace].Add(scores[i]);
placeholder = scores[i];
}
}
return scoresByPlace;
}
Error
Whenever it gets tested with a large array amount (2 Million for examples) it returns an timeout exception (probably HackerRank generated to make it harder)
Attempted solution
Believe it or not but I changed a lot of things on the above code. For one,the results array in the first function used to be a list but I changed to array to make it faster. I feel the dictionary/List is slowing everything down but I need them for the solution (Especially the dictionary). Any Help would be appreciated

C# Console App -- Trying to access a list from else statement

This is for a data structures and algorithms class. We're just starting out with bubble sort. The instructions were to generate random, unique integers and sort them using the sorting technique of the lecture. It will be required to add different sorting techniques as well.
To generate the list of random numbers, I generated a list and then shuffled the list using the fisher-yates algorithm. So I have my unique, sorted list of whatever size I choose.
I'm getting stuck because after I generate the random list, I am having problems accessing the list to run it through BubbleSort.
Is there any way I can do this?
class Algorithms
{
static void Main(string[] args)
{
string response = "";
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
//List<int> toSort = new List<int>();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
// Shuffle(Generate(response));
// have been using the line above but adding next line for
//an idea of my problem
List<int> toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
//This doesn't work and I'm trying to figure out how it can
BubbleSort(toSort);
}
}
}
//Displays help information
public static void Help(string input)
{
Console.WriteLine("\ngenerate <integer> -- Generates a data set of intended amount of integers\n"+
"algorithm <algorithm type> -- Choose which algorithm to sort data\nexit -- exit application\n" );
}
//Generates List of integers from 0 to number choosen by user
public static List<int> Generate(string size)
{
int cutString = size.Length - 9;
string sizeSubset = size.Substring(9, cutString);
List<int> numGen = new List<int>();
int dataSetSize = Convert.ToInt32(sizeSubset);
for(int i = 0; i <= dataSetSize; i++)
{
numGen.Add(i);
// Console.WriteLine(numGen[i]);
}
return numGen;
}
//Use Fisher-Yates algorithm to shuffle the list.
static Random randomize = new Random();
public static List<int> Shuffle(List<int>makeRandom)
{
List<int> shuffled = new List<int>();
int n = makeRandom.Count;
while (n > 1)
{
n--;
int k = randomize.Next(n + 1);
int value = makeRandom[k];
makeRandom[k] = makeRandom[n];
makeRandom[n] = value;
shuffled.Add(value);
Console.WriteLine(value);
}
return shuffled;
}
public static void BubbleSort(List<int>input)
{
for(int i = 0; i <= input.Count; i++)
{
for (int j = 0; j <= (input.Count - 1); j++)
{
if (input[j] > input[j + 1])
{
int temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
Console.WriteLine("hello");
}
}
}
}
}
}
You defined list in scope of else if (response.ToLower().StartsWith("generate")) code block, so it is not accessible outside of that block. Move declaration to Main method scope, like this:
static void Main(string[] args)
{
string response = "";
//define your list here.
List<int> toSort = new List<int>();
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
List<int> sortedList = BubbleSort(toSort);
}
}
}

Foreach list search without repetition [duplicate]

This question already has answers here:
C# creating a list of random unique integers
(6 answers)
Closed 4 years ago.
How I can put randomize numbers to list without repetition?
Here's my code, sometimes the numbers are repeated but I do not know why
Random losowa = new Random();
List<int> pula = new List<int>();
private void LosujPytania()
{
int a = losowa.Next(1,20);
while (pula.Count < 10)
{
foreach (int i in pula)
{
if (a == i)
{
a = losowa.Next(1, 20);
break;
}
}
pula.Add(a);
}
}
Code below create list of numbers without repetition. Key to resolve problem is use list.Contains().
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var list = new List<int>();
var rand = new Random();
while(list.Count <10)
{
var number = rand.Next(1,20);
if(! list.Contains(number))
list.Add(number);
}
foreach(var item in list)
Console.WriteLine(item);
}
}
You should check if this number was previously generated and generate another number if it is repeated.
Change this:
private void LosujPytania()
{
int a = losowa.Next(1,20);
while (pula.Count < 10)
{
foreach (int i in pula)
{
if (a == i)
{
a = losowa.Next(1, 20);
break;
}
}
pula.Add(a);
}
}
by this:
private void LosujPytania()
{
int a = losowa.Next(1,20);
pula.Add(a);
while (pula.Count < 10)
{
do
{
a = losowa.Next(1, 20);
} while(pula.Contains(a));
pula.Add(a);
}
}
You can do this, you can check my comments additional details:
private static void LosujPytania()
{
Random losowa = new Random();
List<int> pula = new List<int>();
int a = losowa.Next(1,20);
while (pula.Count < 10)
{
//Your code is not really checking for duplicates so I replace it with boolean condition below
//foreach (int i in pula)
//{
// if (a == i)
// {
// a = losowa.Next(1, 20);
// break;
// }
//}
a = losowa.Next(1, 20);
//This will check if your list doesn't contain your numbers yet before adding to make sure everything is unique
if (!pula.Contains(a))
pula.Add(a);
}
}
if you want numbers without replications,
I think it will be better to use HashSet.
Random losowa = new Random();
HashSet<int> pula = new HashSet<int>();
while (pula.Count < 10)
{
pula.Add(r.Next(20));
}
or if you really need the List, you can use a helper method
something like:
private void LosujPytania()
{
Random losowa = new Random();
List<int> pula = new List<int>();
int a = losowa.Next(1, 20);
pula.AddRange(Get10RandomNumbers(losowa));
}
private IEnumerable<int> Get10RandomNumbers(Random losowa)
{
HashSet<int> ints = new HashSet<int>();
while (ints.Count < 10)
{
ints.Add(losowa.Next(20));
}
return ints;
}
A simple 2 lines solution:
var rnd = new Random();
var list = Enumerable.Range(0, 20).OrderBy(x => rnd.Next()).Take(10).ToList();
Explanation:
Enumerable.Range(0, 20) will return an IEnumerable<int> with the numbers 0 to 19.
OrderBy(x => rnd.Next()) will sort the values to a random order.
Take(10) will return the first 10 numbers from the IEnumerable<int>,
and finally, ToList() will return a list of these int values.

How to iterate lists with different lengths to find all permutations?

This one should not be too hard but my mind seems to be having a stack overflow (huehue). I have a series of Lists and I want to find all permutations they can be ordered in. All of the lists have different lengths.
For example:
List 1: 1
List 2: 1, 2
All permutations would be:
1, 1
1, 2
In my case I don't switch the numbers around. (For example 2, 1)
What is the easiest way to write this?
I can't say if the following is the easiest way, but IMO it's the most efficient way. It's basically a generalized version of the my answer to the Looking at each combination in jagged array:
public static class Algorithms
{
public static IEnumerable<T[]> GenerateCombinations<T>(this IReadOnlyList<IReadOnlyList<T>> input)
{
var result = new T[input.Count];
var indices = new int[input.Count];
for (int pos = 0, index = 0; ;)
{
for (; pos < result.Length; pos++, index = 0)
{
indices[pos] = index;
result[pos] = input[pos][index];
}
yield return result;
do
{
if (pos == 0) yield break;
index = indices[--pos] + 1;
}
while (index >= input[pos].Count);
}
}
}
You can see the explanation in the linked answer (shortly it's emulating nested loops). Also since for performace reasons it yields the internal buffer w/o cloning it, you need to clone it if you want store the result for later processing.
Sample usage:
var list1 = new List<int> { 1 };
var list2 = new List<int> { 1, 2 };
var lists = new[] { list1, list2 };
// Non caching usage
foreach (var combination in lists.GenerateCombinations())
{
// do something with the combination
}
// Caching usage
var combinations = lists.GenerateCombinations().Select(c => c.ToList()).ToList();
UPDATE: The GenerateCombinations is a standard C# iterator method, and the implementation basically emulates N nested loops (where N is the input.Count) like this (in pseudo code):
for (int i0 = 0; i0 < input[0].Count; i0++)
for (int i1 = 0; i1 < input[1].Count; i1++)
for (int i2 = 0; i2 < input[2].Count; i2++)
...
for (int iN-1 = 0; iN-1 < input[N-1].Count; iN-1++)
yield { input[0][i0], input[1][i1], input[2][i2], ..., input[N-1][iN-1] }
or showing it differently:
for (indices[0] = 0; indices[0] < input[0].Count; indices[0]++)
{
result[0] = input[0][indices[0]];
for (indices[1] = 0; indices[1] < input[1].Count; indices[1]++)
{
result[1] = input[1][indices[1]];
// ...
for (indices[N-1] = 0; indices[N-1] < input[N-1].Count; indices[N-1]++)
{
result[N-1] = input[N-1][indices[N-1]];
yield return result;
}
}
}
Nested loops:
List<int> listA = (whatever), listB = (whatever);
var answers = new List<Tuple<int,int>>;
for(int a in listA)
for(int b in listB)
answers.add(Tuple.create(a,b));
// do whatever with answers
Try this:
Func<IEnumerable<string>, IEnumerable<string>> combine = null;
combine = xs =>
xs.Skip(1).Any()
? xs.First().SelectMany(x => combine(xs.Skip(1)), (x, y) => String.Format("{0}{1}", x, y))
: xs.First().Select(x => x.ToString());
var strings = new [] { "AB", "12", "$%" };
foreach (var x in combine(strings))
{
Console.WriteLine(x);
}
That gives me:
A1$
A1%
A2$
A2%
B1$
B1%
B2$
B2%
I made the following IEnumerable<IEnumerable<TValue>> class to solve this problem which allows use of generic IEnumerable's and whose enumerator returns all permutations of the values, one from each inner list. It can be conventiently used directly in a foreach loop.
It's a variant of Michael Liu's answer to IEnumerable and Recursion using yield return
I've modified it to return lists with the permutations instead of the single values.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Permutation
{
public class ListOfListsPermuter<TValue> : IEnumerable<IEnumerable<TValue>>
{
private int count;
private IEnumerable<TValue>[] listOfLists;
public ListOfListsPermuter(IEnumerable<IEnumerable<TValue>> listOfLists_)
{
if (object.ReferenceEquals(listOfLists_, null))
{
throw new ArgumentNullException(nameof(listOfLists_));
}
listOfLists =listOfLists_.ToArray();
count = listOfLists.Count();
for (int i = 0; i < count; i++)
{
if (object.ReferenceEquals(listOfLists[i], null))
{
throw new NullReferenceException(string.Format("{0}[{1}] is null.", nameof(listOfLists_), i));
}
}
}
// A variant of Michael Liu's answer in StackOverflow
// https://stackoverflow.com/questions/2055927/ienumerable-and-recursion-using-yield-return
public IEnumerator<IEnumerable<TValue>> GetEnumerator()
{
TValue[] currentList = new TValue[count];
int level = 0;
var enumerators = new Stack<IEnumerator<TValue>>();
IEnumerator<TValue> enumerator = listOfLists[level].GetEnumerator();
try
{
while (true)
{
if (enumerator.MoveNext())
{
currentList[level] = enumerator.Current;
level++;
if (level >= count)
{
level--;
yield return currentList;
}
else
{
enumerators.Push(enumerator);
enumerator = listOfLists[level].GetEnumerator();
}
}
else
{
if (level == 0)
{
yield break;
}
else
{
enumerator.Dispose();
enumerator = enumerators.Pop();
level--;
}
}
}
}
finally
{
// Clean up in case of an exception.
enumerator?.Dispose();
while (enumerators.Count > 0)
{
enumerator = enumerators.Pop();
enumerator.Dispose();
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
You can use it directly in a foreach like this:
public static void Main(string[] args)
{
var listOfLists = new List<List<string>>()
{
{ new List<string>() { "A", "B" } },
{ new List<string>() { "C", "D" } }
};
var permuter = new ListOfListsPermuter<string>(listOfLists);
foreach (IEnumerable<string> item in permuter)
{
Console.WriteLine("{ \"" + string.Join("\", \"", item) + "\" }");
}
}
The output:
{ "A", "C" }
{ "A", "D" }
{ "B", "C" }
{ "B", "D" }

Parse CSV string into Array of Integers

I have a text box field inputs 123,145,125 I to separate this field into an array of integers. And validate this field true or false if everything is parsed right.
CODE:
private bool chkID(out int[] val)
{
char[] delimiters = new char[] { ',' };
string[] strSplit = iconeID.Text.Split(delimiters);
int[] intArr = null;
foreach (string s in strSplit) //splits the new parsed characters
{
int tmp;
tmp = 0;
if (Int32.TryParse(s, out tmp))
{
if (intArr == null)
{
intArr = new int[1];
}
else
{
Array.Resize(ref intArr, intArr.Length + 1);
}
intArr[intArr.Length - 1] = tmp;
}
if (Int32.TryParse(iconeID.Text, out tmp))
{
iconeID.BorderColor = Color.Empty;
iconeID.BorderWidth = Unit.Empty;
tmp = int.Parse(iconeID.Text);
val = new int[1];
val[0] = tmp;
return true;
}
}
val = null;
ID.BorderColor = Color.Red;
ID.BorderWidth = 2;
return false;
}
//new Code:
private bool chkID(out int[] val) //bool satus for checkID function
{
string[] split = srtID.Text.Split(new char[1] {','});
List numbers = new List();
int parsed;
bool isOk = true;
foreach( string n in split){
if(Int32.TryParse( n , out parsed))
numbers.Add(parsed);
else
isOk = false;
}
if (isOk){
strID.BorderColor=Color.Empty;
strID.BorderWidth=Unit.Empty;
return true;
} else{
strID.BorderColor=Color.Red;
strID.BorderWidth=2;
return false;
}
return numbers.ToArray();
}
The given function seems to do too much. Here's one that answers the question implied by your title:
//int[] x = SplitStringIntoInts("1,2,3, 4, 5");
static int[] SplitStringIntoInts(string list)
{
string[] split = list.Split(new char[1] { ',' });
List<int> numbers = new List<int>();
int parsed;
foreach (string n in split)
{
if (int.TryParse(n, out parsed))
numbers.Add(parsed);
}
return numbers.ToArray();
}
EDIT (based on your comment on the question)
You've defined the three things this function needs to do. Now you just need to create methods for each. Below are my guesses for how you could implement them.
int[] ValidateIDs(int[] allIDs)
{
List<int> validIDs = new List<int>(allIDs);
//remove invalid IDs
return validIDs.ToArray();
}
void DownloadXmlData(int[] ids)
{
...
}
Now you just execute your new functions:
void CheckIconeID(string ids)
{
int[] allIDs = SplitStringIntoInts(ids);
int[] validIDs = ValidateIDs(allIDs);
DownloadXmlData(validIDs);
}
I really wanted to comment on #Austin Salonen's answer, but it didn't fit. It is a great answer for the question asked, but i wanted to expand the discussion a bit more generally on csv/int conversion part.
It's small point, not worth much debate but I would consider swapping the foreach loop for a plain for loop. You'll likely end up with simpler IL (read faster). See (http://www.codeproject.com/KB/cs/foreach.aspx, http://msdn.microsoft.com/en-us/library/ms973839.aspx [Use For Loops for String Iteration—version 1]).
I would create two methods -- one that is safe and uses TryParse and only adds the "good" values, another that is not as safe, but faster.
Proposed "safe" function (with overload in case you don't want to know the bad values)...
public static int[] SplitAsIntSafe (this string csvString) {
List<string> badVals;
return SplitAsIntSafe(csvString, ',', out badVals);
}
public static int[] SplitAsIntSafe (this string delimitedString, char splitChar, out List<string> badVals) {
int parsed;
string[] split = delimitedString.Split(new char[1] { ',' });
List<int> numbers = new List<int>();
badVals = new List<string>();
for (var i = 0; i < split.Length; i++) {
if (int.TryParse(split[i], out parsed)) {
numbers.Add(parsed);
} else {
badVals.Add(split[i]);
}
}
return numbers.ToArray();
}
Proposed "fast" function ....
public static int[] SplitAsIntFast (this string delimitedString, char splitChar) {
string[] strArray = delimitedString.Split(splitChar);
int[] intArray = new int[strArray.Length];
if(delimitedString == null) {
return new int[0];
}
for (var i = 0; i < strArray.Length; i++) {
intArray[i] = int.Parse(strArray[i]);
}
return intArray;
}
Anyway, hope this helps someone.
It might be worth your while to check out this FileHelper and also CSV Reader
Hope they will help you...
Take care,
Tom
There is a good free library for parsing CSV files: FileHelpers
using FileHelpers;
// First declare the record class
[Delimitedrecord(";")]
public class SampleType
{
public string Field1;
public int Field2;
}
public void ReadExample()
{
FileHelperEngine engine = new FileHelperEngine(typeof(SampleType));
SampleType[] records;
records = (SampleType[]) engine.ReadFile("source.txt");
// Now "records" array contains all the records in the
// sourcefile and can be acceded like this:
int sum = records[0].Field2 + records[1].Field2;
}
public bool ParseAndCheck(string source,
out IList<int> goodItems, out IList<string> badItems)
{
goodItems = new List<int>();
badItems = new List<string>();
foreach (string item in source.Split(','))
{
int temp;
if (int.TryParse(item, out temp))
goodItems.Add(temp);
else
badItems.Add(item);
}
return (badItems.Count < 1);
}
In .NET 2.0 you could write
string test = "123,14.5,125,151,1.55,477,777,888";
bool isParsingOk = true;
int[] results = Array.ConvertAll<string,int>(test.Split(','),
new Converter<string,int>(
delegate(string num)
{
int r;
isParsingOk &= int.TryParse(num, out r);
return r;
}));
This is simple and I think works pretty well. It only return valid numbers:
static int[] SplitStringIntoInts(string list)
{
int dummy;
return (from x in list.Split(',')
where int.TryParse(x.ToString(), out dummy)
select int.Parse(x.ToString())).ToArray();
}

Categories

Resources