Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
C# I want to know How to place a comma after every digit of a long type number (input parameter) separating even and odds?
Example: InsertComma(12272358) should return "1,22,7,2,35,8"
Using LINQ:
private static string InsertComma(long v)
{
var strArray = v.ToString().ToArray();
//compares current element to next one and insert separator if is needed
//last element is ignored due to preventing index exeption
var result = strArray.Take(strArray.Length-1)
.Select((x, index) => ((x % 2) == (strArray[index+1]%2)) ? x.ToString() :x+ ",");
return string.Join("", result)+strArray.Last() ;
}
Using For loop:
private static string InsertComma(long v)
{
var result = "";
var strArray = v.ToString().ToArray();
int i = 0;
for ( i = 0; i < strArray.Length-1; i++)
{
result += strArray[i];
//compares current element to next one and insert separator if is needed
if ((strArray[i]%2) != (strArray[i + 1] % 2))
result += ",";
}
return result + strArray[i];
}
Use:
Console.WriteLine(InsertComma(12272358));
Output:
1,22,7,2,35,8
The simpliest way to enumerate thought a Int's digits is to make it a string.
Then for each element of this string we will lock it it's has the same reminder than the previous element in this case we need to concatenate them. Except for the first element as there is no previous.
var input = 54721704;
var str = input.ToString();
var result = new List<string>();
for (int i = 0; i < str.Length; i++)
{
if (i == 0)
{
result.Add(str[i].ToString());
continue;
}
if (Char.GetNumericValue(str[i]) % 2 == Char.GetNumericValue(str[i - 1]) % 2)
{
result[result.Count() - 1] += str[i].ToString();
}
else
{
result.Add(str[i].ToString());
}
}
Console.WriteLine(string.Join(", ", result));
https://rextester.com/UML19116
You can improve this by avoiding unnecesseray access to the previous element casting and modulo computation by storing the result in a variable.
Covert to string and then loop.
string CovertNumber(int source) {
var result = new StringBuilder();
var src = source.ToString();
var wasEven = false;
for (var i =0; i < src.Length; i++) {
var digit = int.Parse(src[i].ToString());
var isEven = (digit % 2) == 0;
if (i > 0 && isEven != wasEven) {
result.Append(",");
}
result.Append(digit.ToString());
wasEven = isEven;
}
return result.ToString();
}
This code will bomb on a negative number so you will need to validate input or use Math.Abs to ignore the sign.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a string that may contain any letter
string uncompressed = "dacacacd";
I need to compress this string in the format
string compressed = "d3(ac)d";
But also compress any substring if possible ex:
string uncompressed = "dabcabcdabcabc";
string compressed = "2(d2(abc))";
Is there a way to achieve this without any third party library?
Here's an example that will do the compression based on the longest sub-strings first. Maybe not the most efficient or best compression for something like "abababcabc" but should at least get you started.
public class CompressedString
{
private class Segment
{
public Segment(int count, CompressedString value)
{
Count = count;
Value = value;
}
public int Count { get; set; }
public CompressedString Value { get; set; }
}
private List<Segment> segments = new List<Segment>();
private string uncompressible;
private CompressedString(){}
public static CompressedString Compress(string s)
{
var compressed = new CompressedString();
// longest possible repeating substring is half the length of the
// string, so try that first and work down to shorter lengths
for(int len = s.Length/2; len > 0; len--)
{
// look for the substring at each possible index
for(int i = 0; i < s.Length - len - 1; i++)
{
var sub = s.Substring(i, len);
int count = 1;
// look for repeats of the substring immediately after it.
for(int j = i + len; j <= s.Length - len; j += len)
{
// increase the count of times the substring is found
// or stop looking when it doesn't match
if(sub == s.Substring(j, len))
{
count++;
}
else
{
break;
}
}
// if we found repeats then handle the substring before the
// repeats, the repeast, and everything after.
if(count > 1)
{
// if anything is before the repeats then add it to the
// segments with a count of one and compress it.
if (i > 0)
{
compressed.segments.Add(new Segment(1, Compress(s.Substring(0, i))));
}
// Add the repeats to the segments with the found count
// and compress it.
compressed.segments.Add(new Segment(count, Compress(sub)));
// if anything is after the repeats then add it to the
// segments with a count of one and compress it.
if (s.Length - (count * len) > i)
{
compressed.segments.Add(new Segment(1, Compress(s.Substring(i + (count * len)))));
}
// We're done compressing so break this loop and the
// outer by setting len to 0.
len = 0;
break;
}
}
}
// If we failed to find any repeating substrings then we just have
// a single uncompressible string.
if (!compressed.segments.Any())
{
compressed.uncompressible = s;
}
// Reduce the the compression for something like "2(2(ab))" to "4(ab)"
compressed.Reduce();
return compressed;
}
private void Reduce()
{
// Attempt to reduce each segment.
foreach(var seg in segments)
{
seg.Value.Reduce();
// If there is only one sub segment then we can reduce it.
if(seg.Value.segments.Count == 1)
{
var subSeg = seg.Value.segments[0];
seg.Value = subSeg.Value;
seg.Count *= subSeg.Count;
}
}
}
public override string ToString()
{
if(segments.Any())
{
StringBuilder builder = new StringBuilder();
foreach(var seg in segments)
{
if (seg.Count == 1)
builder.Append(seg.Value.ToString());
else
{
builder.Append(seg.Count).Append("(").Append(seg.Value.ToString()).Append(")");
}
}
return builder.ToString();
}
return uncompressible;
}
}
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;
}
}
This is not homework, although it may seem like it. I've been browsing through the UK Computing Olympiad's website and found this problem (Question 1): here. I was baffled by it, and I'd want to see what you guys thought of how to do it. I can't think of any neat ways to get everything into groups (checking whether it's a palindrome after that is simple enough, i.e. originalString == new String(groupedString.Reverse.SelectMany(c => c).ToArray), assuming it is a char array).
Any ideas? Thanks!
Text for those at work:
A palindrome is a word that shows the same sequence of letters when
reversed. If a word can have its letters grouped together in two or
more blocks (each containing one or more adjacent letters) then it is
a block palindrome if reversing the order of those blocks results in
the same sequence of blocks.
For example, using brackets to indicate blocks, the following are
block palindromes:
• BONBON can be grouped together as (BON)(BON);
• ONION can be grouped together as (ON)(I)(ON);
• BBACBB can be grouped together as (B)(BACB)(B) or (BB)(AC)(BB) or
(B)(B)(AC)(B)(B)
Note that (BB)(AC)(B)(B) is not valid as the reverse (B)(B)(AC)(BB)
shows the blocks in a different order.
And the question is essentially how to generate all of those groups, to then check whether they are palindromes!
And the question is essentially how to generate all of those groups, to then check whether they are palindromes!
I note that this is not necessarily the best strategy. Generating all the groups first and then checking to see if they are palidromes is considerably more inefficient than generating only those groups which are palindromes.
But in the spirit of answering the question asked, let's solve the problem recursively. I will just generate all the groups; checking whether a set of groups is a palindrome is left as an exercise. I am also going to ignore the requirement that a set of groups contains at least two elements; that is easily checked.
The way to solve this problem elegantly is to reason recursively. As with all recursive solutions, we begin with a trivial base case:
How many groupings are there of the empty string? There is only the empty grouping; that is, the grouping with no elements in it.
Now we assume that we have a solution to a smaller problem, and ask "if we had a solution to a smaller problem, how could we use that solution to solve a larger problem?"
OK, suppose we have a larger problem. We have a string with 6 characters in it and we wish to produce all the groupings. Moreover, the groupings are symmetrical; the first group is the same size as the last group. By assumption we know how to solve the problem for any smaller string.
We solve the problem as follows. Suppose the string is ABCDEF. We peel off A and F from both ends, we solve the problem for BCDE, which remember we know how to do by assumption, and now we prepend A and append F to each of those solutions.
The solutions for BCDE are (B)(C)(D)(E), (B)(CD)(E), (BC)(DE), (BCDE). Again, we assume as our inductive hypothesis that we have the solution to the smaller problem. We then combine those with A and F to produce the solutions for ABCDEF: (A)(B)(C)(D)(E)(F), (A)(B)(CD)(E)(F), (A)(BC)(DE)(F) and (A)(BCDE)(F).
We've made good progress. Are we done? No. Next we peel off AB and EF, and recursively solve the problem for CD. I won't labour how that is done. Are we done? No. We peel off ABC and DEF and recursively solve the problem for the empty string in the middle. Are we done? No. (ABCDEF) is also a solution. Now we're done.
I hope that sketch motivates the solution, which is now straightforward. We begin with a helper function:
public static IEnumerable<T> AffixSequence<T>(T first, IEnumerable<T> body, T last)
{
yield return first;
foreach (T item in body)
yield return item;
yield return last;
}
That should be easy to understand. Now we do the real work:
public static IEnumerable<IEnumerable<string>> GenerateBlocks(string s)
{
// The base case is trivial: the blocks of the empty string
// is the empty set of blocks.
if (s.Length == 0)
{
yield return new string[0];
yield break;
}
// Generate all the sequences for the middle;
// combine them with all possible prefixes and suffixes.
for (int i = 1; s.Length >= 2 * i; ++i)
{
string prefix = s.Substring(0, i);
string suffix = s.Substring(s.Length - i, i);
string middle = s.Substring(i, s.Length - 2 * i);
foreach (var body in GenerateBlocks(middle))
yield return AffixSequence(prefix, body, suffix);
}
// Finally, the set of blocks that contains only this string
// is a solution.
yield return new[] { s };
}
Let's test it.
foreach (var blocks in GenerateBlocks("ABCDEF"))
Console.WriteLine($"({string.Join(")(", blocks)})");
The output is
(A)(B)(C)(D)(E)(F)
(A)(B)(CD)(E)(F)
(A)(BC)(DE)(F)
(A)(BCDE)(F)
(AB)(C)(D)(EF)
(AB)(CD)(EF)
(ABC)(DEF)
(ABCDEF)
So there you go.
You could now check to see whether each grouping is a palindrome, but why? The algorithm presented above can be easily modified to eliminate all non-palindromes by simply not recursing if the prefix and suffix are unequal:
if (prefix != suffix) continue;
The algorithm now enumerates only block palindromes. Let's test it:
foreach (var blocks in GenerateBlocks("BBACBB"))
Console.WriteLine($"({string.Join(")(", blocks)})");
The output is below; again, note that I am not filtering out the "entire string" block but doing so is straightforward.
(B)(B)(AC)(B)(B)
(B)(BACB)(B)
(BB)(AC)(BB)
(BBACBB)
If this subject interests you, consider reading my series of articles on using this same technique to generate every possible tree topology and every possible string in a language. It starts here:
http://blogs.msdn.com/b/ericlippert/archive/2010/04/19/every-binary-tree-there-is.aspx
This should work:
public List<string> BlockPalin(string s) {
var list = new List<string>();
for (int i = 1; i <= s.Length / 2; i++) {
int backInx = s.Length - i;
if (s.Substring(0, i) == s.Substring(backInx, i)) {
var result = string.Format("({0})", s.Substring(0, i));
result += "|" + result;
var rest = s.Substring(i, backInx - i);
if (rest == string.Empty) {
list.Add(result.Replace("|", rest));
return list;
}
else if (rest.Length == 1) {
list.Add(result.Replace("|", string.Format("({0})", rest)));
return list;
}
else {
list.Add(result.Replace("|", string.Format("({0})", rest)));
var recursiveList = BlockPalin(rest);
if (recursiveList.Count > 0) {
foreach (var recursiveResult in recursiveList) {
list.Add(result.Replace("|", recursiveResult));
}
}
else {
//EDIT: Thx to #juharr this list.Add is not needed...
// list.Add(result.Replace("|",string.Format("({0})",rest)));
return list;
}
}
}
}
return list;
}
And call it like this (EDIT: Again thx to #juharr, the distinct is not needed):
var x = BlockPalin("BONBON");//.Distinct().ToList();
var y = BlockPalin("ONION");//.Distinct().ToList();
var z = BlockPalin("BBACBB");//.Distinct().ToList();
The result:
x contains 1 element: (BON)(BON)
y contains 1 element: (ON)(I)(ON)
z contains 3 elements: (B)(BACB)(B),(B)(B)(AC)(B)(B) and (BB)(AC)(BB)
Although not so elegant as the one provided by #Eric Lippert, one might find interesting the following iterative string allocation free solution:
struct Range
{
public int Start, End;
public int Length { get { return End - Start; } }
public Range(int start, int length) { Start = start; End = start + length; }
}
static IEnumerable<Range[]> GetPalindromeBlocks(string input)
{
int maxLength = input.Length / 2;
var ranges = new Range[maxLength];
int count = 0;
for (var range = new Range(0, 1); ; range.End++)
{
if (range.End <= maxLength)
{
if (!IsPalindromeBlock(input, range)) continue;
ranges[count++] = range;
range.Start = range.End;
}
else
{
if (count == 0) break;
yield return GenerateResult(input, ranges, count);
range = ranges[--count];
}
}
}
static bool IsPalindromeBlock(string input, Range range)
{
return string.Compare(input, range.Start, input, input.Length - range.End, range.Length) == 0;
}
static Range[] GenerateResult(string input, Range[] ranges, int count)
{
var last = ranges[count - 1];
int midLength = input.Length - 2 * last.End;
var result = new Range[2 * count + (midLength > 0 ? 1 : 0)];
for (int i = 0; i < count; i++)
{
var range = result[i] = ranges[i];
result[result.Length - 1 - i] = new Range(input.Length - range.End, range.Length);
}
if (midLength > 0)
result[count] = new Range(last.End, midLength);
return result;
}
Test:
foreach (var input in new [] { "BONBON", "ONION", "BBACBB" })
{
Console.WriteLine(input);
var blocks = GetPalindromeBlocks(input);
foreach (var blockList in blocks)
Console.WriteLine(string.Concat(blockList.Select(range => "(" + input.Substring(range.Start, range.Length) + ")")));
}
Removing the line if (!IsPalindromeBlock(input, range)) continue; will produce the answer to the OP question.
It's not clear if you want all possible groupings, or just a possible grouping. This is one way, off the top-of-my-head, that you might get a grouping:
public static IEnumerable<string> GetBlocks(string testString)
{
if (testString.Length == 0)
{
yield break;
}
int mid = testString.Length / 2;
int i = 0;
while (i < mid)
{
if (testString.Take(i + 1).SequenceEqual(testString.Skip(testString.Length - (i + 1))))
{
yield return new String(testString.Take(i+1).ToArray());
break;
}
i++;
}
if (i == mid)
{
yield return testString;
}
else
{
foreach (var block in GetBlocks(new String(testString.Skip(i + 1).Take(testString.Length - (i + 1) * 2).ToArray())))
{
yield return block;
}
}
}
If you give it bonbon, it'll return bon. If you give it onion it'll give you back on, i. If you give it bbacbb, it'll give you b,b,ac.
Here's my solution (didn't have VS so I did it using java):
int matches = 0;
public void findMatch(String pal) {
String st1 = "", st2 = "";
int l = pal.length() - 1;
for (int i = 0; i < (pal.length())/2 ; i ++ ) {
st1 = st1 + pal.charAt(i);
st2 = pal.charAt(l) + st2;
if (st1.equals(st2)) {
matches++;
// DO THE SAME THING FOR THE MATCH
findMatch(st1);
}
l--;
}
}
The logic is pretty simple. I made two array of characters and compare them to find a match in each step. The key is you need to check the same thing for each match too.
findMatch("bonbon"); // 1
findMatch("bbacbb"); // 3
What about something like this for BONBON...
string bonBon = "BONBON";
First check character count for even or odd.
bool isEven = bonBon.Length % 2 == 0;
Now, if it is even, split the string in half.
if (isEven)
{
int halfInd = bonBon.Length / 2;
string firstHalf = bonBon.Substring(0, halfInd );
string secondHalf = bonBon.Substring(halfInd);
}
Now, if it is odd, split the string into 3 string.
else
{
int halfInd = (bonBon.Length - 1) / 2;
string firstHalf = bonBon.Substring(0, halfInd);
string middle = bonBon.Substring(halfInd, bonBon.Length - halfInd);
string secondHalf = bonBon.Substring(firstHalf.Length + middle.length);
}
May not be exactly correct, but it's a start....
Still have to add checking if it is actually a palindrome...
Good luck!!
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I am trying to make a prime number generator.
I get three errors:
<21,22> expected >
<21,23> expression > is invalid
<21,24> expected ;
translated errors from norwegian. they may not be exact
using System;
namespace Primtall
{
class Program
{
static void Main(string[] args)
{
Generator G = new Generator();
G.gen();
}
}
public class Generator
{
int a = 0;
int divident = 0;
public void gen()
{
for (a; a<100; a++;)
{
for (divident; divident <= 50;divident++)
{
int div = a/divident;
if((div % 1) == 0)
{
Console.WriteLine(a);
}
else
{
break;
}
}
}
}
}
}
There is no need to define a and divident variables as fields. You make no use of them except in the loop. In fact, using class members (fields) as loop variables will immediately render your class as "not thread safe", becuase if two seperate threads execute the gen() method on the same Generator instance they will both fail to get correct results
Change your Generator class like this: (divident starting from 1 to avoid divide by zero exception)
public class Generator
{
public void gen()
{
for (int a = 0; a < 100; a++)
{
for (int divident = 1; divident <= 50; divident++)
{
int div = a / divident;
if ((div % 1) == 0)
{
Console.WriteLine(a);
}
else
{
break;
}
}
}
}
}
You declare variables before loops, so you must leave empty first argument in for:
for (; a < 100; a++)
{
for (; divident <= 50; divident++)
{
Or better declare loop variables in loop:
for (var a = 0; a < 100; a++)
{
for (var divident = 2; divident <= a / 2; divident++)
{
Also, you have some problems in algorithm:
int div = a/divident;
if((div % 1) == 0)
Should be replaced with:
if((a % divident) == 0)
{
flag = false;
break;
}
Declare flag in first loop as true and check it after second loop finish. If it's stil true - number is prime. Also, start second loop with 2 and end with a / 2
You seem to be misunderstanding how for loops work
for(Initialise; While; Action)
so in english what you are asking it to do is
for
a where a starts at 0
while a less than 100
perform body
then increment a by 1
this in code is
For(int a = 0;a<100;a++)
{
//body
}