I am trying to create a function that will create all permutations of a string in an incremental fashion. I would like to start at:
AAAAA
...
AAAAB
...
ACCCC
...
...
ZZZZZ
I have looked around, and can't seem to find anything of that sort. I tried to create it, but it wasn't incrementally.
Any suggestions?
The "permutation" you are describing is better known as the Cartesian product. If you have an arbitrary number of sequences that you need to form the Cartesian product of, see my answer to this question on the subject:
Generating all Possible Combinations
Normally I wouldn't help these brute force type results... but seeing how many useless result you will get out of the set I figured I'd just toss this in.
var query = from c0 in Enumerable.Range(0, 26)
from c1 in Enumerable.Range(0, 26)
from c2 in Enumerable.Range(0, 26)
from c3 in Enumerable.Range(0, 26)
from c4 in Enumerable.Range(0, 26)
select new string(
new [] {
(char)('A' + c0),
(char)('A' + c1),
(char)('A' + c2),
(char)('A' + c3),
(char)('A' + c4),
}
);
BTW... if you just want the next value you can do something like this...
public static string Increment(string input)
{
var array = input.ToCharArray();
if (array.Any(c => c < 'A' || c > 'Z'))
throw new InvalidOperationException();
for (var i = array.Length-1; i >= 0; i--)
{
array[i] = (char)(array[i] + 1);
if (array[i] > 'Z')
{
array[i] = 'A';
if (i == 0)
return 'A' + new string(array);
}
else
break;
}
return new string(array);
}
A different variant where I had the idea of using modulo arithmetic. Note that I lowered the character to {A,B,C} to test it, since going up to Z for 5 letters is a lot of strings.
public IEnumerable<char[]> AlphaCombinations(int length = 5, char startChar = 'A', char endChar = 'C')
{
int numChars = endChar - startChar + 1;
var s = new String(startChar, length).ToCharArray();
for (int it = 1; it <= Math.Pow(numChars, length); ++it)
{
yield return s;
for (int ix = 0; ix < s.Length; ++ix)
if (ix == 0 || it % Math.Pow(numChars, ix) == 0)
s[s.Length - 1 - ix] = (char)(startChar + (s[s.Length - 1 - ix] - startChar + 1) % numChars);
}
}
...
foreach (var s in AlphaCombinations(5))
{
Console.WriteLine(s);
}
Bashed out quickly - I expect this could be done better:
public static IEnumerable<string> GenerateStrings(int length = 5)
{
var buffer = new char[length];
for (int i = 0; i < length; ++i)
{
buffer[i] = 'A';
}
for(;;)
{
yield return new string(buffer);
int cursor = length;
for(;;)
{
--cursor;
if (cursor < 0)
{
yield break;
}
char c = buffer[cursor];
++c;
if (c <= 'Z')
{
buffer[cursor] = c;
break;
}
else
{
buffer[cursor] = 'A';
}
}
}
}
Here is the LINQPad friendly code and it uses lambda expression.
void Main()
{
var chars = Enumerable.Range(65, 26);
var strings = chars.SelectMany (a =>
{
return chars.SelectMany (b => chars.SelectMany (c =>
{
return chars.SelectMany (d =>
{
return chars.Select (e => {return new string(new char[] {(char)a, (char)b, (char)c, (char)d, (char)e});});
});
}));
});
strings.Dump();
}
Related
I am trying to rearrange a given string, so no two adjacent letters are the same.
For that I'm thinking to count every distinct letter's occurence, and then rearrange the string the characters occurence number
example:
Input: AABAABBC
Output: AAAABBBC
and after that spliting it in 2 different strings
AAAA BBBC
and then trying to get the final result.
My question is how do I rearrange the string without using Linq?
Here is my code so far:
private static string GetDistinctChars(string text)
{
string result = "";
foreach (char c in text)
{
if (!result.Contains(c))
{
result += c;
}
}
return result;
}
private static double GetCharOccurrence(string text, char charToCount)
{
int count = 0;
foreach (char c in text)
{
if (c == charToCount)
{
count++;
}
}
return count;
}
You can do it like that:
string example = "AABBAACDCAA";
var orderList = example.OrderBy(x => x).ToList();
List<string> letters = new List<string>();
string temp = string.Empty;
for(int i = 0; i < orderList.Count; i++)
{
temp += orderList[i];
if (i + 1 == orderList.Count)
{
letters.Add(temp);
break;
}
if(orderList[i] != orderList[i + 1])
{
letters.Add(temp);
temp = string.Empty;
}
}
string result = String.Join(" ", letters);
Console.WriteLine(result);
If you don't want to use Linq Order by method, you should implement sorting algorithm like this:
static char[] SortArray(char[] array)
{
int length = array.Length;
char temp = array[0];
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length; j++)
{
if (array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
return array;
}
and use it in your program:
string example = "AABBAACDCAA";
var orderList = SortArray(example.ToCharArray());
List<string> letters = new List<string>();
string temp = string.Empty;
for(int i = 0; i < orderList.Length; i++)
{
temp += orderList[i];
if (i + 1 == orderList.Length)
{
letters.Add(temp);
break;
}
if(orderList[i] != orderList[i + 1])
{
letters.Add(temp);
temp = string.Empty;
}
}
string result = String.Join(" ", letters);
Console.WriteLine(result);
alternativly, if you don't want to use list anymore, you can operate only on strigns:
string example = "AABBAACDCAA";
var orderList = SortArray(example.ToCharArray());
string lettersString = string.Empty;
for (int i = 0; i < orderList.Length; i++)
{
lettersString += orderList[i];
if (i + 1 == orderList.Length)
break;
if (orderList[i] != orderList[i + 1])
lettersString += " ";
}
Console.WriteLine(lettersString);
You can find your problem on LeetCode, it's a problem #767.
My algorithm is
If we have too many of same characters, we can't solve the problem (e.g. "aaaaaabc")
If solution exists, we can sort characters aababc -> aaabbc and then take item by item from the beginning and from the center:
For instance:
aababc -> aaabbc (ordered by frequency: a appears 3 time, b - 2, c - 1)
then
aaabbc => ab
^ ^
take these
aaabbc => abab
^ ^
take these
aaabbc => ababac <- final answer
^ ^
take these
Code:
using System.Linq;
using System.Text;
...
public static string ReorganizeString(string s) {
int count = s.GroupBy(c => c).Max(g => g.Count());
// One of the item is too frequent, no solutions
if (count > (s.Length + 1) / 2)
return "";
string st = string.Concat(s
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // not required, just for aesthetic
.SelectMany(c => c));
StringBuilder sb = new StringBuilder(s.Length);
for (int i = 0; i < s.Length / 2; ++i) {
sb.Append(st[i]);
sb.Append(st[(st.Length + 1) / 2 + i]);
}
// Middle character
if (s.Length % 2 != 0)
sb.Append(st[st.Length / 2]);
return sb.ToString();
}
Demo:
string value = "AABAABBC";
Console.Write(ReorganizeString(value));
Output:
ABABABAC
Fiddle it yourself.
Edit: If StringBuilder (as well as System.Text) is really forbidden, we can use string, which, however, slows down the routine:
using System.Linq;
...
public static string ReorganizeString(string s) {
int count = s.GroupBy(c => c).Max(g => g.Count());
// One of the item is too frequent, no solutions
if (count > (s.Length + 1) / 2)
return "";
string st = string.Concat(s
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // not required, just for aesthetic
.SelectMany(c => c));
string result = "";
for (int i = 0; i < s.Length / 2; ++i) {
result += st[i];
result += st[(st.Length + 1) / 2 + i];
}
// Middle character
if (s.Length % 2 != 0)
result += st[st.Length / 2];
return result;
}
I'm working on a program that encodes and decodes letters to numbers. I have the Encoding properly built but the decoding is giving me problems. I'm using int to char conversions with the ASCII table as the key. It doesn't seem like the conversion logic for the decoding is right but I really have no idea how to fix it. This is my first time using this conversion method so I still don't fully understand it.
*edit This is on a windows form app that has three buttons and two text boxes. Encode is one button, and you type in a sentence and it outputs in in numbers for each letter. Decode is another but it does the opposite type in numbers and get words. the third button is clear so thats not important. Sorry I left this out of the initial question.
class LetterCodeLogic
{
public static string Encode(string msg)
{
string result = "";
string m = msg.ToUpper();
char c;
int x;
for(int i = 0; i < m.Length; i++)
{
c = Convert.ToChar(m[i]);
x = c;
if (x == 32)
{
x = 0;
}
else
{
x -= 64;
if (x < 1 || x > 26)
{
x = 99;
}
}
result += x.ToString() + " ";
}
return result;
}
public static string Decode(string msg)
{
string result = "";
string[] nums = msg.Split(',');
char c;
int x;
for (int i = 0; i < msg.Length; i++)
{
x = Convert.ToChar(msg[i]);
c = (char)x;
if (c == 0)
{
c = (char)32;
}
else
{
c -= (char)64;
if (c < 65 || c > 90)
{
c = (char)35;
}
}
result += c.ToString() + " ";
}
return result;
}
}
I find problems like this are far easier when you break them into parts. First, write functions that convert a single character to a number or vice versa.
static public byte Encode(char c)
{
if (c == ' ') return 0;
if (c >= 'A' && c <= 'Z') return (byte)(c - 'A' + 1);
return 99;
}
static public char Decode(byte n)
{
if (n == 0) return ' ';
if (n >= 1 && n <= 27) return (char)(n + 'A' - 1);
return '#';
}
Now the functions you need are very easy to write:
static public string Encode(string stringInput)
{
return string.Join(" ", stringInput.Select(Encode).Select( b => b.ToString() ));
}
static public string Decode(string numericInput)
{
return new string(numericInput.Split(' ').Select( n => byte.Parse(n)).Select(Decode).ToArray());
}
I'm facing a problem I don't even know what to search in Google/Stack Overflow.
So comment if you feel the need for further explanation, questions.
Basically I want to intersect two lists and return the similarity with the preserved order of the original first string value.
Example:
I have two strings, that I convert to a CharArray.
I want to Intersect these two arrays and return the values that are similar, including/with the order of the first string (s1).
As you can see the first string contains E15 (in that specific order), and so does the seconds one.
So these two strings will return : { 'E', '1', '5' }
string s1 = "E15QD(A)";
string s2 = "NHE15H";
The problem I am facing is that if i replace "s2" with:
string s2 = "NQE18H" // Will return {'Q', 'E', '1' }
My operation will return : {'Q', 'E', '1' }
The result should be : {'E', '1' } because Q don't follow the letter 1
Currently my operation is not the greatest effort, because i don't know which methods to use in .NET to be able to do this.
Current code:
List<char> cA1 = s1.ToList();
List<char> cA2 = s2.ToList();
var result = cA1.Where(x => cA2.Contains(x)).ToList();
Feel free to help me out, pointers in the right direction is acceptable as well as a full solution.
This is a "longest common substring" problem.
You can use this extension to get all substrings lazily:
public static class StringExtensions
{
public static IEnumerable<string> GetSubstrings(this string str)
{
if (string.IsNullOrEmpty(str))
throw new ArgumentException("str must not be null or empty", "str");
for (int c = 0; c < str.Length - 1; c++)
{
for (int cc = 1; c + cc <= str.Length; cc++)
{
yield return str.Substring(c, cc);
}
}
}
}
Then it's easy and readable with this LINQ query:
string longestIntersection = "E15QD(A)".GetSubstrings()
.Intersect("NQE18H".GetSubstrings())
.OrderByDescending(s => s.Length)
.FirstOrDefault(); // E1
Enumerable.Intersect is also quite efficient since it's using a set. One note: if one both strings is larger than the other then it's more efficient(in terms of memory) to use it first:
longString.GetSubstrings().Intersect(shortString.GetSubstrings())
I think this should do it:
string similar = null;
for (int i = 0; i < s1.Length; i++)
{
string s = s1.Substring(0, i + 1);
if (s2.Contains(s))
{
similar = s;
}
}
char[] result = similar.ToCharArray();
#TimSchmelter provided the link to this answer in the comments of the original post.
public int LongestCommonSubstring(string str1, string str2, out string sequence)
{
sequence = string.Empty;
if (String.IsNullOrEmpty(str1) || String.IsNullOrEmpty(str2))
return 0;
int[,] num = new int[str1.Length, str2.Length];
int maxlen = 0;
int lastSubsBegin = 0;
StringBuilder sequenceBuilder = new StringBuilder();
for (int i = 0; i < str1.Length; i++)
{
for (int j = 0; j < str2.Length; j++)
{
if (str1[i] != str2[j])
num[i, j] = 0;
else
{
if ((i == 0) || (j == 0))
num[i, j] = 1;
else
num[i, j] = 1 + num[i - 1, j - 1];
if (num[i, j] > maxlen)
{
maxlen = num[i, j];
int thisSubsBegin = i - num[i, j] + 1;
if (lastSubsBegin == thisSubsBegin)
{//if the current LCS is the same as the last time this block ran
sequenceBuilder.Append(str1[i]);
}
else //this block resets the string builder if a different LCS is found
{
lastSubsBegin = thisSubsBegin;
sequenceBuilder.Length = 0; //clear it
sequenceBuilder.Append(str1.Substring(lastSubsBegin, (i + 1) - lastSubsBegin));
}
}
}
}
}
sequence = sequenceBuilder.ToString();
return maxlen;
}
Given a string, move all digit elements to end of string. While moving elements, keep the relative order of all positioned elements same.
For example, if the given string is
a1b2c3d4e5f6g7h8i9j1k2l3m4
convert it to
abcdefghijklm1234567891234
in-place and in O(n) time complexity.
I got a different result
abcdefghijklm7481951326324
Also I failed for testing another string
aHR0cDovL3d3dy5nZWVrc2ZvcmdlZWtzLm9yZy9hbi1pbi1wbGFjZS1hbGdvcml0aG0tZm9yLXN0cmluZy10cmF
Code:
static string s = "a1b2c3d4e5f6g7h8i9j1k2l3m4";
static void Main(string[] args)
{
char[] input = s.ToCharArray();
string output = arrangeList(input);
Console.WriteLine(output);
Console.WriteLine("Another test");
s = "aHR0cDovL3d3dy5nZWVrc2ZvcmdlZWtzLm9yZy9hbi1pbi1wbGFjZS1hbGdvcml0aG0tZm9yLXN0cmluZy10cmF";
input = s.ToCharArray();
output = arrangeList(input);
Console.WriteLine(output);
Console.Read();
}
private static string arrangeList(char[] x)
{
for (int i = 1; i < x.Length - 1; i++)
{
int j = i + 1;
while (j < x.Length)
{
if ( (x[j] > '0' && x[j] < '9') && x[i] > '9')
{
swap(x, i, j); j++;
break;
}
if ( (x[i] > '0' && x[i] < '9') && x[j] > '9')
{
swap(x, i, j); j++;
break;
}
j++;
}
}
return new string(x);
}
private static void swap(char[] a, int i, int j)
{
char temp = a[i];
a[i] = a[j];
a[j] = temp;
}
With Linq
var input = "a1b2c3d4e5f6g7h8i9j1k2l3m4";
var output = String.Join("", input.GroupBy(c => char.IsDigit(c))
.OrderBy(x => x.Key) //Always 2 items to sort. Not O(N*logN)
.SelectMany(g => g));
You can build it in a character array pretty easily by working from the back to copy digits and from the front to copy letters. That is:
var input = "a1b2c3d4e5f6g7h8i9j1k2l3m4";
int ixLetter = 0;
int ixDigit = input.Length - 1;
int oxLetter = 0;
int oxDigit = input.Length - 1;
char[] output = new char[input.Length];
while (ixDigit >= 0)
{
if (char.IsDigit(input[ixDigit]))
{
output[oxDigit] = input[ixDigit];
--oxDigit;
}
if (!char.IsDigit(input[ixLetter]))
{
output[oxLetter] = input[ixLetter];
++oxLetter;
}
--ixDigit;
++ixLetter;
}
string result = new string(output);
This does two passes over the string, one from the front and one from the back. Complexity is linear, thus O(n).
Now, doing it in a single pass ... I'd have to think a bit about that.
This works, uses linq, and has O(n) time complexity:
var input = #"123vcvcv00191pololo";
var array =
input
.ToCharArray()
.Where(c => !Char.IsDigit(c))
.Concat(
input
.ToCharArray()
.Where(c => Char.IsDigit(c)))
.ToArray();
var output = new String(array);
Console.Write(output);
// vcvcvpololo12300191
using linq's OrderBy as shown should move all the digits to the end of the string/char[] in the order in which they appear in the string.
var input = #"123vcvcv00191pololo";
var array = input.ToCharArray().OrderBy(c => Char.IsDigit(c)).ToArray();
var output = new String(array);
Console.Write(output);
//vcvpololo12300191
I am solving the same problem as here Project Euler #22 Python, 2205 points missing?, but I am using C#. I can't find the mistake. Here is my code:
class Program
{
static List<string> pole;
static string SaveName(StreamReader reader)
{
int znak = reader.Read();
string jmeno = "";
while ((znak < 'A') || (znak > 'Z'))
{
znak = reader.Read();
}
while (znak != ',')
{
jmeno = jmeno + (char) znak;
znak = reader.Read();
if (znak == 34) break;
}
return jmeno;
}
static void SaveNamesIntoList()
{
StreamReader reader = new StreamReader(#"../../../names.txt");
while (reader.Read() != ';')
{
pole.Add(SaveName(reader));
}
}
static void Main(string[] args)
{
pole = new List<string>();
SaveNamesIntoList();
pole.Sort();
int sum = 0;
int sum_word = 0;
string name = "";
for (int i = 0; i < pole.Count; i++)
{
name = pole[i];
sum_word = 0;
for (int u = 0; u < name.Length; u++)
{
sum_word += (name[u] - 'A' + 1);
}
sum += (sum_word * (i+1));
}
Console.WriteLine(sum);
}
}
Thanks for any answer:)
Ther reason why you have different result is than Czech language has specific letter 'CH' whitch is after 'H' so in alfabetical order without using right culture you can have sometring like this
aaa
bbb
ccc
czz
ddd
cha
There are a few issues here. You don't check if the reader reached the end of stream - you have to check if the Read returned -1. If it did - it's the end of the file. On top of that, you don't dispose the reader...
Then, as Cedric noted in the comments, you haven't really sorted the list, hence the result is wrong even after changing it to:
using (var reader = new StreamReader("names.txt"))
{
while (reader.Read() != -1)
{
pole.Add(SaveName(reader));
}
}
What you need to do is add this line (which is a bit wasteful in general, but I'll get to that in a sec):
pole = pole.OrderBy(x => x).ToList(); //<<----- this one
for (int i = 0; i < pole.Count; i++)
{
name = pole[i];
sum_word = 0;
for (int u = 0; u < name.Length; u++)
{
sum_word += (name[u] - 'A' + 1);
}
sum2 += (sum_word*(i + 1));
}
And the result is 871198282, which should be correct - at least that's what the people are saying in the linked question.
Even then, might I suggest an easier way of solving that whole problem:
var scores = Enumerable.Range('A', 'Z' - 'A' + 1)
.Select((i, ch) => new { Character = (char) i, Weight = ch + 1 })
.ToDictionary(key => key.Character, val => val.Weight);
var sum = File.ReadAllText("names.txt")
.Split(',')
.Select(x => x.Trim('"'))
.OrderBy(x => x)
.Select((x, i) => (i + 1)*x.Select(y => scores[y]).Sum())
.Sum();
Here's a version using Linq.
void Main()
{
var file = #"C:\...location.of.file...\p022_names.txt";
using (var reader = new StreamReader(file, Encoding.UTF8))
{
NameScore(reader.ReadToEnd().Replace("\"",string.Empty).Split(new[]{','})).Dump();
}
}
private long NameScore(string[] names)
{
return names.OrderBy(o => o)
.Select((l, i) => { return l.ToUpper().ToCharArray().Sum(s => (int)s - 64) * (i + 1);})
.Sum(s => s);
}