List<string> arguments = new List<string>(Environment.GetCommandLineArgs().Skip(1).Take(4));
int variant = consoleOptions.HandleInput(arguments);
public int HandleInput(List<string> input)
{
int variant = 0;
//for (int i = 0; i < input.Count; i++)
//{
// if (input[i].Contains("-s"))
// {
// variant = 1;
// }
//}
if (input[0].Contains("-s"))
{
variant = 1;
if (!String.IsNullOrWhiteSpace(input[1]) && !String.IsNullOrWhiteSpace(input[2]))
{
variant = 2;
}
if (!String.IsNullOrWhiteSpace(input[3]))
{
variant = 3;
}
}
return variant;
}
I'm starting my application from Commandline.
Then I get a List of Strings (max 4).
What I want to do now is:
if the first String in List is "-s" then variant = 1
if the second and third string isn't Empty then variant = 2
if the fourth string isn't Empty then variant = 3
I tried some things (Code above), but the problem is, if I only get the first String (one item),
The Compiler crashes on other place (checking Second string, cause Index not accessible)..
What would be the best method?
The Take(4) doesn't guarantee that you'll have 4 elements, it just means you won't have more than 4. So you have to check the list length.
if (input.Count >= 1 && input[0].Contains("-s"))
{
return 1;
}
if (input.Count >= 3)
{
return 2;
}
if (input.Count >= 4)
{
return 3;
}
return 0; //what do you return if none of the conditions are met?
you try some thing like this.
if (input[0].Contains("-s"))
{
variant = 1;
}
if (!String.IsNullOrWhiteSpace(input[1]) && !String.IsNullOrWhiteSpace(input[2]))
{
variant = 2;
}
if (!String.IsNullOrWhiteSpace(input[3]))
{
variant = 3;
}
return variant;
Related
E.g. If we have an array [1,2,3,4,6,7,8] then 1 then 2 then 3 then 4 are all consecutive but 6 is not, so that's the first non-consecutive number.
If the whole array is consecutive then return null .
The array will always have at least 2 elements 1 and all elements will be numbers. The numbers will also all be unique and in ascending order. The numbers could be positive or negative and the first non-consecutive could be either too. please help me finish this code i am new in programming. My code:
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace _2katas
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var input = this.txtInput.Text;
var numarray = input.Split(',');
int firstValue = Convert.ToInt32(numarray[0]);
for (var i = 0; i < numarray.Length; i++)
{
if (Convert.ToInt32(numarray[i]) - i != firstValue)
{
lblPrint.Text = "";
}
else
{
lblPrint.Text = "";
}
if (this.rdbConsecutive.Checked == true)
{
lblKataRunning.Text = "Consecutive";
}
else if (this.rdbStripCleaning.Checked == true)
{
lblKataRunning.Text = "Strip Cleaning";
}
}
}
}
}
Let's extract a method:
Find the first element of an array that is not consecutive ...
If the whole array is consecutive then return null
We can implement it like this:
private static string FirstInconsecutive(string data) {
var array = data.Split(',');
if (array.Length <= 0)
return null; //TODO: what shall we return on empty array?
if (!int.TryParse(array[0], out int delta))
return array[0];
for (int i = 1; i < array.Length; ++i)
if (!int.TryParse(array[i], out int value) || value - i != delta)
return array[i];
return null;
}
Usage:
string result = FirstInconsecutive(txtInput.Text);
Please note int.TryParse which helps to return the right answer "ABC" on an input like "1, 2, 3, ABC, 4, 6, 7, 8" (user input txtInput.Text can contain any string)
A linq solution just for the fun of it:
static int? FindFirstNonConsecutive(IEnumerable<int> arr)
{
var nonConsecutiveInfo =
arr.Select((i, index) => new {Index = index, Delta = i - index})
.FirstOrDefault(t => t.Delta != arr.First());
return nonConsecutiveInfo?.Delta + nonConsecutiveInfo?.Index;
}
Note that this will only work finding non consecutive numbers in ascending order as per requirements.
Two numbers are not consecutive if the left ones + 1 <> the right one.
Check with something like this, note that you have to change your boundary checks:
for (var i = 0; i < numarray.Length - 1; i++)
{
if (Convert.ToInt32(numarray[i]) + 1 != Convert.ToInt32(numarray[i+1]))
Update your condition as below for loop and it will work. I would suggest you to have separate function so that it could be reusable if needed elsewhere in code.
Here start your loop from i = 1 and compare numarray[i-1] + 1 != numarray[i] values.
You can convert your sting[] to int[] with var numarray = input.Split(',').Select(x => Convert.ToInt32(x)).ToArray(); and use it with IsConsecutive(numarray) as per button1_Click code.
You can get first non-consecutive value with minor modification in return type and return statement as shown in GetFirstNonConsecutiveValue().
public bool IsConsecutive(int[] numarray)
{
for (int i = 1; i < numarray.Length; i++)
{
if (numarray[i-1] + 1 != numarray[i])
{
return false;
}
}
return true;
}
public int? GetFirstNonConsecutiveValue(int[] numarray)
{
for (int i = 1; i < numarray.Length; i++)
{
if (numarray[i-1] + 1 != numarray[i])
{
return numarray[i];
}
}
return null;
}
private void button1_Click(object sender, EventArgs e)
{
var input = this.txtInput.Text;
var numarray = input.Split(',').Select(x => Convert.ToInt32(x)).ToArray();
var nonConsecutiveValue = GetFirstNonConsecutiveValue(numarray);
if (nonConsecutiveValue != null)
{
// nonConsecutiveValue is first non consecutive value.
}
else
{
// sequence is consecutive.
}
}
One way to go.
string rawData = "1,2,3,4,6,7,8,9";
IEnumerable<int> data = rawData.Split(',').Select(v => Convert.ToInt32(v));
IEnumerable<int> all = Enumerable.Range(data.Min(), data.Max() - data.Min() + 1);
IEnumerable<int> diff = all.Except(data);
if (diff.Count() == 0)
{
return null;
}
return data.ElementAt(all.ToList().IndexOf(diff.First()))
NB Not thoroughly tested.
Just test diff for being empty to get the numbers are consecutive
I have to make a string which consists a string like - AAA0009, and once it reaches AAA0009, it will generate AA0010 to AAA0019 and so on.... till AAA9999 and when it will reach to AAA9999, it will give AAB0000 to AAB9999 and so on till ZZZ9999.
I want to use static class and static variables so that it can auto increment by itself on every hit.
I have tried some but not even close, so help me out thanks.
Thanks for being instructive I was trying as I Said already but anyways you already want to put negatives over there without even knowing the thing:
Code:
public class GenerateTicketNumber
{
private static int num1 = 0;
public static string ToBase36()
{
const string base36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var sb = new StringBuilder(9);
do
{
sb.Insert(0, base36[(byte)(num1 % 36)]);
num1 /= 36;
} while (num1 != 0);
var paddedString = "#T" + sb.ToString().PadLeft(8, '0');
num1 = num1 + 1;
return paddedString;
}
}
above is the code. this will generate a sequence but not the way I want anyways will use it and thanks for help.
Though there's already an accepted answer, I would like to share this one.
P.S. I do not claim that this is the best approach, but in my previous work we made something similar using Azure Table Storage which is a no sql database (FYI) and it works.
1.) Create a table to store your running ticket number.
public class TicketNumber
{
public string Type { get; set; } // Maybe you want to have different types of ticket?
public string AlphaPrefix { get; set; }
public string NumericPrefix { get; set; }
public TicketNumber()
{
this.AlphaPrefix = "AAA";
this.NumericPrefix = "0001";
}
public void Increment()
{
int num = int.Parse(this.NumericPrefix);
if (num + 1 >= 9999)
{
num = 1;
int i = 2; // We are assuming that there are only 3 characters
bool isMax = this.AlphaPrefix == "ZZZ";
if (isMax)
{
this.AlphaPrefix = "AAA"; // reset
}
else
{
while (this.AlphaPrefix[i] == 'Z')
{
i--;
}
char iChar = this.AlphaPrefix[i];
StringBuilder sb = new StringBuilder(this.AlphaPrefix);
sb[i] = (char)(iChar + 1);
this.AlphaPrefix = sb.ToString();
}
}
else
{
num++;
}
this.NumericPrefix = num.ToString().PadLeft(4, '0');
}
public override string ToString()
{
return this.AlphaPrefix + this.NumericPrefix;
}
}
2.) Make sure you perform row-level locking and issue an error when it fails.
Here's an oracle syntax:
SELECT * FROM TICKETNUMBER WHERE TYPE = 'TYPE' FOR UPDATE NOWAIT;
This query locks the row and returns an error if the row is currently locked by another session.
We need this to make sure that even if you have millions of users generating a ticket number, it will not mess up the sequence.
Just make sure to save the new ticket number before you perform a COMMIT.
I forgot the MSSQL version of this but I recall using WITH (ROWLOCK) or something. Just google it.
3.) Working example:
static void Main()
{
TicketNumber ticketNumber = new TicketNumber();
ticketNumber.AlphaPrefix = "ZZZ";
ticketNumber.NumericPrefix = "9999";
for (int i = 0; i < 10; i++)
{
Console.WriteLine(ticketNumber);
ticketNumber.Increment();
}
Console.Read();
}
Output:
Looking at your code that you've provided, it seems that you're backing this with a number and just want to convert that to a more user-friendly text representation.
You could try something like this:
private static string ValueToId(int value)
{
var parts = new List<string>();
int numberPart = value % 10000;
parts.Add(numberPart.ToString("0000"));
value /= 10000;
for (int i = 0; i < 3 || value > 0; ++i)
{
parts.Add(((char)(65 + (value % 26))).ToString());
value /= 26;
}
return string.Join(string.Empty, parts.AsEnumerable().Reverse().ToArray());
}
It will take the first 4 characters and use them as is, and then for the remainder of the value if will convert it into characters A-Z.
So 9999 becomes AAA9999, 10000 becomes AAB0000, and 270000 becomes ABB0000.
If the number is big enough that it exceeds 3 characters, it will add more letters at the start.
Here's an example of how you could go about implementing it
void Main()
{
string template = #"AAAA00";
var templateChars = template.ToCharArray();
for (int i = 0; i < 100000; i++)
{
templateChars = IncrementCharArray(templateChars);
Console.WriteLine(string.Join("",templateChars ));
}
}
public static char Increment(char val)
{
if(val == '9') return 'A';
if(val == 'Z') return '0';
return ++val;
}
public static char[] IncrementCharArray(char[] val)
{
if (val.All(chr => chr == 'Z'))
{
var newArray = new char[val.Length + 1];
for (int i = 0; i < newArray.Length; i++)
{
newArray[i] = '0';
}
return newArray;
}
int length = val.Length;
while (length > -1)
{
char lastVal = val[--length];
val[length] = Increment(lastVal);
if ( val[length] != '0') break;
}
return val;
}
My problem should be quite simple. I have a random generated string that changes multiple times per second. I want to return 1 if it appears x times consecutively.
My current code:
string s; //this is the generated string
int checker = 0;
string[] s_list = null;
if( cheaker == 0)
{
s_list[0] = s;
}
else if( cheaker == 1)
{
s_list[1] = s;
}
checker++;
if(s_list[0] == s_list[1]) return 1;
My problem is that I want to be able to change the amount of x times if appears and like this it will generate tons of code if the x is too big.
Do you think putting the current string into an array of string and compare them is the best way? There should be a better implementation.
To make the code generic for any given X, you should keep last X strings and check whether all they are equal, e.g.:
List<string> list = new List<string>();
if (list.Count >= X)
{
list.RemoveAt(0);
}
list.Add(newString);
return list.Count >= X && list.Any(s => s == list[0]);
I assume s_list is an array where you store all the generations of the string
string s;
string[] s_list;
// Your logic that would generate s and store it in s_list
// ...
// ...
int required_amount = 10; // whatever X amount you want
int current_sequence = 0;
// It's important to start at 1, and not 0,
// as you compare to the previous entry each time
for(int i = 1; i < s_list.Lenght; i++ )
{
if( s_list[i] == s_list[i-1] )
{
current_sequence++;
if(current_sequence >= required_amount)
{
return 1;
}
}
else
{
current_sequence = 0;
}
}
For my problem I have a list of a count larger then 6+. From that list I would like to make a list containing every possible combination of the original cards that is exactly 6 cards long. (they have to be unique and order doesn't matter)
so object
01,02,03,04,05,06
is the same for me as
06,05,04,03,02,01
//STARTER list with more then 6 value's
List < ClassicCard > lowCardsToRemove = FrenchTarotUtil.checkCountLowCardForDiscardChien(handCards);
The solution i found and used:
public static List generateAllSubsetCombinations(object[] fullSet, ulong subsetSize) {
if (fullSet == null) {
throw new ArgumentException("Value cannot be null.", "fullSet");
}
else if (subsetSize < 1) {
throw new ArgumentException("Subset size must be 1 or greater.", "subsetSize");
}
else if ((ulong)fullSet.LongLength < subsetSize) {
throw new ArgumentException("Subset size cannot be greater than the total number of entries in the full set.", "subsetSize");
}
// All possible subsets will be stored here
List<object[]> allSubsets = new List<object[]>();
// Initialize current pick; will always be the leftmost consecutive x where x is subset size
ulong[] currentPick = new ulong[subsetSize];
for (ulong i = 0; i < subsetSize; i++) {
currentPick[i] = i;
}
while (true) {
// Add this subset's values to list of all subsets based on current pick
object[] subset = new object[subsetSize];
for (ulong i = 0; i < subsetSize; i++) {
subset[i] = fullSet[currentPick[i]];
}
allSubsets.Add(subset);
if (currentPick[0] + subsetSize >= (ulong)fullSet.LongLength) {
// Last pick must have been the final 3; end of subset generation
break;
}
// Update current pick for next subset
ulong shiftAfter = (ulong)currentPick.LongLength - 1;
bool loop;
do {
loop = false;
// Move current picker right
currentPick[shiftAfter]++;
// If we've gotten to the end of the full set, move left one picker
if (currentPick[shiftAfter] > (ulong)fullSet.LongLength - (subsetSize - shiftAfter)) {
if (shiftAfter > 0) {
shiftAfter--;
loop = true;
}
}
else {
// Update pickers to be consecutive
for (ulong i = shiftAfter+1; i < (ulong)currentPick.LongLength; i++) {
currentPick[i] = currentPick[i-1] + 1;
}
}
} while (loop);
}
return allSubsets;
}
This one is not from me, but it does the job!
List <ClassicCard> lowCardsToRemove = FrenchTarotUtil.checkCountLowCardForDiscardChien(handCards);
var result = Combinator.Combinations(lowCardsToRemove, 6);
public static class Combinator
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
}
Is there any simple algorithm to determine the likeliness of 2 names representing the same person?
I'm not asking for something of the level that Custom department might be using. Just a simple algorithm that would tell me if 'James T. Clark' is most likely the same name as 'J. Thomas Clark' or 'James Clerk'.
If there is an algorithm in C# that would be great, but I can translate from any language.
Sounds like you're looking for a phonetic-based algorithms, such as soundex, NYSIIS, or double metaphone. The first actually is what several government departments use, and is trivial to implement (with many implementations readily available). The second is a slightly more complicated and more precise version of the first. The latter-most works with some non-English names and alphabets.
Levenshtein distance is a definition of distance between two arbitrary strings. It gives you a distance of 0 between identical strings and non-zero between different strings, which might also be useful if you decide to make a custom algorithm.
Levenshtein is close, although maybe not exactly what you want.
I've faced similar problem and tried to use Levenstein distance first, but it did not work well for me. I came up with an algorithm that gives you "similarity" value between two strings (higher value means more similar strings, "1" for identical strings). This value is not very meaningful by itself (if not "1", always 0.5 or less), but works quite well when you throw in Hungarian Matrix to find matching pairs from two lists of strings.
Use like this:
PartialStringComparer cmp = new PartialStringComparer();
tbResult.Text = cmp.Compare(textBox1.Text, textBox2.Text).ToString();
The code behind:
public class SubstringRange {
string masterString;
public string MasterString {
get { return masterString; }
set { masterString = value; }
}
int start;
public int Start {
get { return start; }
set { start = value; }
}
int end;
public int End {
get { return end; }
set { end = value; }
}
public int Length {
get { return End - Start; }
set { End = Start + value;}
}
public bool IsValid {
get { return MasterString.Length >= End && End >= Start && Start >= 0; }
}
public string Contents {
get {
if(IsValid) {
return MasterString.Substring(Start, Length);
} else {
return "";
}
}
}
public bool OverlapsRange(SubstringRange range) {
return !(End < range.Start || Start > range.End);
}
public bool ContainsRange(SubstringRange range) {
return range.Start >= Start && range.End <= End;
}
public bool ExpandTo(string newContents) {
if(MasterString.Substring(Start).StartsWith(newContents, StringComparison.InvariantCultureIgnoreCase) && newContents.Length > Length) {
Length = newContents.Length;
return true;
} else {
return false;
}
}
}
public class SubstringRangeList: List<SubstringRange> {
string masterString;
public string MasterString {
get { return masterString; }
set { masterString = value; }
}
public SubstringRangeList(string masterString) {
this.MasterString = masterString;
}
public SubstringRange FindString(string s){
foreach(SubstringRange r in this){
if(r.Contents.Equals(s, StringComparison.InvariantCultureIgnoreCase))
return r;
}
return null;
}
public SubstringRange FindSubstring(string s){
foreach(SubstringRange r in this){
if(r.Contents.StartsWith(s, StringComparison.InvariantCultureIgnoreCase))
return r;
}
return null;
}
public bool ContainsRange(SubstringRange range) {
foreach(SubstringRange r in this) {
if(r.ContainsRange(range))
return true;
}
return false;
}
public bool AddSubstring(string substring) {
bool result = false;
foreach(SubstringRange r in this) {
if(r.ExpandTo(substring)) {
result = true;
}
}
if(FindSubstring(substring) == null) {
bool patternfound = true;
int start = 0;
while(patternfound){
patternfound = false;
start = MasterString.IndexOf(substring, start, StringComparison.InvariantCultureIgnoreCase);
patternfound = start != -1;
if(patternfound) {
SubstringRange r = new SubstringRange();
r.MasterString = this.MasterString;
r.Start = start++;
r.Length = substring.Length;
if(!ContainsRange(r)) {
this.Add(r);
result = true;
}
}
}
}
return result;
}
private static bool SubstringRangeMoreThanOneChar(SubstringRange range) {
return range.Length > 1;
}
public float Weight {
get {
if(MasterString.Length == 0 || Count == 0)
return 0;
float numerator = 0;
int denominator = 0;
foreach(SubstringRange r in this.FindAll(SubstringRangeMoreThanOneChar)) {
numerator += r.Length;
denominator++;
}
if(denominator == 0)
return 0;
return numerator / denominator / MasterString.Length;
}
}
public void RemoveOverlappingRanges() {
SubstringRangeList l = new SubstringRangeList(this.MasterString);
l.AddRange(this);//create a copy of this list
foreach(SubstringRange r in l) {
if(this.Contains(r) && this.ContainsRange(r)) {
Remove(r);//try to remove the range
if(!ContainsRange(r)) {//see if the list still contains "superset" of this range
Add(r);//if not, add it back
}
}
}
}
public void AddStringToCompare(string s) {
for(int start = 0; start < s.Length; start++) {
for(int len = 1; start + len <= s.Length; len++) {
string part = s.Substring(start, len);
if(!AddSubstring(part))
break;
}
}
RemoveOverlappingRanges();
}
}
public class PartialStringComparer {
public float Compare(string s1, string s2) {
SubstringRangeList srl1 = new SubstringRangeList(s1);
srl1.AddStringToCompare(s2);
SubstringRangeList srl2 = new SubstringRangeList(s2);
srl2.AddStringToCompare(s1);
return (srl1.Weight + srl2.Weight) / 2;
}
}
Levenstein distance one is much simpler (adapted from http://www.merriampark.com/ld.htm):
public class Distance {
/// <summary>
/// Compute Levenshtein distance
/// </summary>
/// <param name="s">String 1</param>
/// <param name="t">String 2</param>
/// <returns>Distance between the two strings.
/// The larger the number, the bigger the difference.
/// </returns>
public static int LD(string s, string t) {
int n = s.Length; //length of s
int m = t.Length; //length of t
int[,] d = new int[n + 1, m + 1]; // matrix
int cost; // cost
// Step 1
if(n == 0) return m;
if(m == 0) return n;
// Step 2
for(int i = 0; i <= n; d[i, 0] = i++) ;
for(int j = 0; j <= m; d[0, j] = j++) ;
// Step 3
for(int i = 1; i <= n; i++) {
//Step 4
for(int j = 1; j <= m; j++) {
// Step 5
cost = (t.Substring(j - 1, 1) == s.Substring(i - 1, 1) ? 0 : 1);
// Step 6
d[i, j] = System.Math.Min(System.Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
}
}
// Step 7
return d[n, m];
}
}
I doubt there is, considering even the Customs Department doesn't seem to have a satisfactory answer...
If there is a solution to this problem I seriously doubt it's a part of core C#. Off the top of my head, it would require a database of first, middle and last name frequencies, as well as account for initials, as in your example. This is fairly complex logic that relies on a database of information.
Second to Levenshtein distance, what language do you want? I was able to find an implementation in C# on codeproject pretty easily.
In an application I worked on, the Last name field was considered reliable.
So presented all the all the records with the same last name to the user.
User could sort by the other fields to look for similar names.
This solution was good enough to greatly reduce the issue of users creating duplicate records.
Basically looks like the issue will require human judgement.