so I'm working on this problem: https://www.hackerrank.com/challenges/30-review-loop/problem (it's in C#)
and so far I'm just trying to break it down piece by piece, and so far I was able to get it to show every other character, but I'm not sure how to concatenate each letter into a new string.
My code for the problem is as follows I've commented out the two for loops, because I felt like there was a more elegant solution to this than what I had, but I didn't want to lose where I was in case another path proved to be more challenging.
using System;
using System.Collections.Generic;
using System.IO;
class Solution {
static void Main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution */
int inputQTY = Int32.Parse(Console.ReadLine());
string input = Console.ReadLine(); // The example gives us the first word to be Hacker then the next word Rank on the next line, so the outputs would be Hce akr, and Rn ak respectively.
int strLen = input.Length;
char[] inputCharArray = input.ToCharArray();
string output = "";
/*
for (int j = 0; j < inputQTY; j++){
for (int i = 0; i < strLen; i++) {
if (j % 2 == 0 && i % 2 == 0) {
Console.WriteLine(inputCharArray[i]);
output = new string (new char[] {inputCharArray[i]});
Console.WriteLine(output);
Console.WriteLine("This is i: {0}", i);
Console.WriteLine("This is j: {0}", j);
Console.WriteLine("--------------");
Console.WriteLine("");
}
else {
Console.WriteLine("This is the next j part hopefully: {0}", j);
}
}
}*/
}
}
Like I understand I need to first step through the word, grab every other letter, then step through the word again and grab the remaining letters, then concatenate those letters into words, and concatenate those words into a sentence, so j would be the loop giving me the two words where I is the loop getting the two words put together..... but I'm having a difficult time wrapping my head around where I'm going wrong here. On top of this, I feel like there's another approach entirely that I'm missing, using commands I may not even know about.
Anyhoo any help is appreciated, hopefully I won't be so green after this. Thanks!
Ok so I ended up solving it with the following code, thank you for all your help everyone!
I ended up solving it with the following code (in C#):
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
class Solution {
static void Main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution */
int count = Int32.Parse(Console.ReadLine());
for (int k = 0; k < count; k++) {
char[] word = Console.ReadLine().ToCharArray();
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < word.Length; i+=2) {
sb1.Append(word[i]);
}
for (int j = 1; j < word.Length; j+=2) {
sb2.Append(word[j]);
}
Console.WriteLine(sb1 + " " + sb2);
}
}
}
LINQ version, updated to fix index error:
output = $"{new string(s.Where((x,i) => i % 2 == 0).ToArray())} {new string(s.Where((x,i) => i % 2 != 0).ToArray())}";
To explain, you're grabbing every character whose index in the string is evenly divisible by 2 and printing it, then every character in the string whose index is not evenly divisible by 2 and printing it.
Update:
Since I was asked for further explanation. First, here's the full code that runs successfully in the HackerRank challenge:
using System;
using System.Collections.Generic;
using System.Linq;
class Solution
{
static void Main(String[] args)
{
List<string> tests = new List<string>();
var testCount = int.Parse(Console.ReadLine());
for (var i = 0; i < testCount; i++)
{
tests.Add(Console.ReadLine());
}
foreach (var s in tests)
{
Console.WriteLine($"{new string(s.Where((x, i) => i % 2 == 0).ToArray())} {new string(s.Where((x, i) => i % 2 != 0).ToArray())}");
}
}
}
Regarding what each section of the code does:
i % 2 == 0
This is a test to see if a number is evenly divisible by two, or an even number.
s.Where((x,i) => i % 2 == 0)
This says, for the array of characters that make up the string 's', return all characters (the result is an IEnumerable) where that character's index (location in the string) is an even number.
new string(s.Where((x,i) => i % 2 == 0).ToArray())
This says to take that IEnumerable of characters with even numbered indexes and return them to an Array of characters. Then, create a new string out of that array of characters.
For the odd numbers, it's the same, but you use != 0 in the mod.
I used this simple method of appending to two StringBuilder objects
var sb1 = new StringBuilder();
var sb2 = new StringBuilder();
int i = 0;
foreach (char c in input)
{
var sb = (i % 2 == 0 ? sb1 : sb2);
sb.Append(c);
i = i + 1;
}
output = sb1.ToString() + " " + sb2.ToString();
this is the long way..
int count = int.Parse(Console.ReadLine());
for(int k = 0; k < count; k++){
char[] inputChars = Console.ReadLine().ToCharArray();
char[] evenChars = new char[inputChars.Length % 2 == 0 ? inputChars.Length / 2 : (inputChars.Length + 1) / 2];
char[] oddChars = new char[inputChars.Length - evenChars.Length];
int evenIndex=0,oddIndex = 0;
for(int i = 0; i < inputChars.Length;i++)
if(i % 2 == 0)
evenChars[evenIndex++] = inputChars[i];
else
oddChars[oddIndex++] = inputChars[i];
Console.WriteLine(string.Format("{0} {1}",string.Concat(evenChars),string.Concat(oddChars)));
}
an alternative..
int count = int.Parse(Console.ReadLine());
for(int k = 0; k < count; k++){
string input = Console.ReadLine();
Enumerable.Range(0, input.Length)
.OrderBy(o => o % 2 != 0)
.Select(o => {
if(o == 1)
Console.Write(" ");
Console.Write(input[o]);
return input[o];
}).ToArray();
Console.Write("\n");
}
Related
Say I have a string like
Line 1
Line 2
I want to turn this string 90 degrees clockwise, so that it becomes
LL
ii
nn
ee
12
The rotation needs to be performed only once such that it is in effect 'turning lines into columns.' Performing it twice should give the original string. (If it was truly rotating by 90 degrees, it would have to be repeated four times to arrive back at the original.)
using System;
using System.Collections;
using System.Collections.Generic;
namespace rotateString
{
class Program
{
static void Main(string[] args)
{
var strings = new string[] { "Line 1", "Line 2" };
var lines = new List<string>();
var done = false;
var j = 0;
do
{
var line = "";
for (var i = 0; i < strings.Length; ++i)
{
var s = strings[i];
if (j >= s.Length)
{
done = true;
break;
}
line += s[j];
}
lines.Add(line);
++j;
} while (!done);
for(int i=0; i < lines.Count; ++i)
{
Console.WriteLine(string.Format("{0} : '{1}'", i, lines[i]));
}
}
}
}
Output:
0 : 'LL'
1 : 'ii'
2 : 'nn'
3 : 'ee'
4 : ' '
5 : '12'
6 : ''
Note that this pretty much assumes the strings are all the same length. Adjusting it to work with the longest string length is trivial.
Using a StringBuilder would be a bit more efficient but, unless you're working with a lot of very long strings, you'll never see the difference in performance.
This was interesting to try out and write. I haven't spent time on validation and characters, but I was trying to see if I can write something that is somewhat "compact" (challenge to myself mostly in evening hours).
#KayZed I will also run your implementation, I see you did some more validations about the inputs.
#3Dave I see we had similar ideas about this ;)
My idea around this was a projection of the input strings (plus now I hard-coded the length of the Span<char>, that calculation can be made simple) into the "flattened" structure of all characters with the offset of the index based on the number of inputs.
My "solution":
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
var inputs = new[] { "Short", "Line 1", "Line 2", "Much longer line 3", "🧐" };
Rotate(inputs);
}
public static void Rotate(IReadOnlyCollection<string> aValues)
{
Span<char> chars = stackalloc char[100];
var offset = 0;
foreach (var value in aValues)
{
var index = 0;
foreach (char character in value)
{
chars[index + offset] = character;
index += aValues.Count;
}
offset++;
}
var position = 0;
foreach (char character in chars)
{
Console.Write(character == default(char) ? ' ' : character);
Console.Write(' ');
if (position == aValues.Count - 1)
{
Console.WriteLine();
position = 0;
continue;
}
position++;
}
}
}
I probably missed some edge cases (and didn't handle the "special" characters), but hope this gives an idea on some "optimisations".
The output:
S L L M �
h i i u �
o n n c
r e e h
t
1 2 l
o
n
g
e
r
l
i
n
e
3
It will need to add leading spaces (i.e. columns which were preceding shorter lines in the original string.) This method gives you an option to make this visible (fillChar - several options provided as constants.)
Also the additional ReverseLineOrder method reverses the line order in case you would want to rotate 90 degrees, reversing all lines.
using System;
using System.Globalization;
using System.Text;
namespace Library.Text
{
public static class TextRotate
{
public const char Space = ' ';
public const char MiddleDot = '\u00b7';
public const char Circle = '\u25cb';
public const char BlackSquare = '\u25a0';
public const char NoBreakSpace = '\u00a0';
public static string LinesToColumns(string s, char fillChar = Space)
{
// A line feed at the end of the text is not seen as content.
// However, if the text ends in a line feed, we make sure the output ends in one, too.
bool endsWithNewline = s.EndsWith(Environment.NewLine);
string[] linesIn = s.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
int[][] textElements = new int[linesIn.Length][];
int longestLine_chars = 0;
int longestLine_elems = 0; // The longest line, in text elements
for (int l = 0; l < linesIn.Length; l++)
{
string line = linesIn[l];
if (line.Length > longestLine_chars)
{
longestLine_chars = line.Length;
}
var elems = StringInfo.ParseCombiningCharacters(line); // Gets indices of surrogate pairs, combining characters etc.
if (elems.Length > longestLine_elems)
{
longestLine_elems = elems.Length;
}
textElements[l] = elems;
}
// Go through columns (columns in the input text, and columns in terms of text elements - NOT chars)
string[] columns = new string[longestLine_elems];
var builder = new StringBuilder(longestLine_chars * linesIn.Length + Math.Max(longestLine_chars, linesIn.Length) * Environment.NewLine.Length);
for (int column = 0; column < longestLine_elems; column++)
{
builder.Clear();
System.Diagnostics.Debug.Assert(builder.Length == 0);
int cutoff = 0;
for (int l = 0; l < linesIn.Length; l++)
{
// Is the line long enough to reach to this column?
int[] lineTextElements = textElements[l];
int textElementsInLine = lineTextElements.Length;
if (textElementsInLine > column)
{
int firstCharIndex = lineTextElements[column];
if (column + 1 < textElementsInLine)
{
int nrOfChars = lineTextElements[column + 1] - firstCharIndex;
builder.Append(linesIn[l], firstCharIndex, nrOfChars);
}
else
{
builder.Append(linesIn[l], firstCharIndex, linesIn[l].Length - firstCharIndex);
}
cutoff = builder.Length;
}
else
{
builder.Append(fillChar);
}
}
// Trim the fill char off line endings (for when rotating back)
while (cutoff > 0 && builder[cutoff - 1] == fillChar)
{
cutoff--;
}
// Resulting column
columns[column] = builder.ToString(0, cutoff);
}
// Turn the columns into lines
builder.Clear();
foreach (var c in columns)
{
builder.AppendLine(c);
}
if (!endsWithNewline && builder.Length > 0)
{
builder.Length -= Environment.NewLine.Length;
}
return builder.ToString();
}
public static string ReverseLineOrder(string s)
{
// A line feed at the end of the text is not seen as content.
// However, if the text ends in a line feed, we make sure the output ends in one, too.
bool endsWithNewline = s.EndsWith(Environment.NewLine);
string[] linesIn = s.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
var builder = new StringBuilder(s.Length);
for (int l = linesIn.Length - (endsWithNewline ? 2 : 1); l >= 0; l--)
{
builder.AppendLine(linesIn[l]);
}
if (!endsWithNewline && builder.Length > 0)
{
builder.Length -= Environment.NewLine.Length;
}
return builder.ToString();
}
}
}
I have been trying to fix this issue for some days now but can't find the error. It seems as simple as an if statement for the code to print commas for all but the last number. It worked for me putting random numbers but when i put the specific numbers (24,7,35,2,27,7,89)it prints the comma at the end.
Print even numbers with commas
This is my code, but i tried multiple other ways.
using System.Collections.Generic;
using System.Text;
using System.Transactions;
namespace ArrayExercises
{
class TaskFour
{
public static void FindEvenNumbers()
{
int[] input = new int[7];
int count = 1;
string comma = ",";
Console.WriteLine("[== Please Enter 7 numbers ==]");
Console.WriteLine();
for (int i = 0; i < input.Length; i++)
{
Console.WriteLine($"Enter number {count}:");
input[i] = int.Parse(Console.ReadLine());
count++;
}
Console.WriteLine("The even numbers in this array are: ");
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
if (i < input.Length)
{
Console.Write(input[i] + comma);
}
else
{
Console.Write(input[i]);
}
}
}
}
}
}
Thanks in advance :)
You can use below code without introducing any extra space using for loop.
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
if (i != 0) Console.Write(comma);
Console.Write(input[i]);
}
}
Or use the inbuilt string.Join function.
Console.WriteLine(string.Join(',', input.Where(i => i % 2 == 0)));
This answer assumes that the above is homework/tutorial, there are more efficient means that what I am posting here
The problem is this segment:
if (i < input.Length)
{
Console.Write(input[i] + comma);
}
The problem is that you are always outputting a comma, regardless of what is to follow. I think that the easiest approach would be to add the comma before hand, meaning, while you are going through the second loop, if you have already printed a number before, you pre-pend a comma and print the number you have, if you did not print any numbers before (that is, you are about to print the first number) then you do not prepend the comma.
i will always be less than the length the input due to the loop's condition.
Instead of implementing this yourself, you could let string.join do the heavy lifting for you:
string result = string.Join(comma, input.Where(i => i % 2 == 0));
Console.WriteLine(result);
Your else condition will never execute. If you are rookie in C# then I would suggest get all even numbers first and store it in the list. Iterate over again to print with comma and just skip the last comma.
//Your existing source code
List<int> evenNumber = new List<int>();
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
evenNumber.Add(input[i]);
}
}
for(int i = 0; i < evenNumber.Length; i++)
{
//Print just number if it is last, otherwise print number with comma
if(i == evenNumber.Length - 1)
Console.Write(evenNumber[i]);
else
Console.Write(evenNumber[i]+comma);
}
If you know string.Join() then use linq to get list of even numbers and print list of even numbers with ',' as a delimiter
var evenNumbers = input.Where(x => x % 2 ==0); //Filter all even numbers
Console.WriteLine(string.Join(",", evenNumbers); //Print using string.Join
Yet another version:
string result = "";
for (int i = 0; i < input.Length; i++)
{
if (input[i] % 2 == 0)
{
result += $",{input[i]}";
}
}
Console.WriteLine( result.Length > 0 ? result.Substring(1).ToString() : "");
I am new to C# and trying a demo program in this program my intended output is:
Id 1 2 3 4 5 6 7 8 9
Roll # 1 2 3 4 5 6 7 8 9
and this is what I have tried :
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
sb.Append("Id ");
for (int i = 0; i < 10; i++)
{
sb.Append(i+" ");
}
sb.AppendLine();
sb.Append("Roll# ");
for (int i = 0; i < 10; i++)
{
sb.Append(i + " ");
}
Console.WriteLine(sb);
}
though it gives me desired output but here I have to iterate through for loop twice. Is there any way by which only iterating once I can get the same output, using some string formatting of C#?
This can be done without explicit looping, using Enumerable.Range to "generate a sequence of integral numbers within a specified range", along with string.Join() to concatenate the previously created range with the string " " :
// using System.Linq;
string range = string.Join(" ", Enumerable.Range(1, 10)); // "1 2 3 4 5 6 7 8 9 10"
sb.AppendLine($"Id {range}");
sb.AppendLine($"Roll# {range}");
If you really want to use a for loop to build your sequence, you can build your own Range method such as :
public static IEnumerable<int> Range(int min, int max)
{
if (min > max)
{
throw new ArgumentException("The min value can't be greater than the max");
}
for (int i = min; i <= max; i++)
{
yield return i;
}
}
And then Join like previously :
var range = string.Join(" ", Range(1, 10));
sb.AppendLine($"Id {range}");
sb.AppendLine($"Roll# {range}");
Or build an array/List/whatever collection and then use string.Join() :
var arr = new int [10];
for (int i = 1; i <= 10; i++)
{
arr[i - 1] = i;
}
string range = string.Join(" ", arr);
sb.AppendLine($"Id {range}");
sb.AppendLine($"Roll# {range}");
Or directly build a string in the loop :
var sbRange = new StringBuilder();
for (int i = 1; i <= 10; i++)
{
sbRange.Append($"{i} ");
}
// You can use a string and trim it (there is a space in excess at the end)
string range = sbRange.ToString().Trim();
sb.AppendLine($"Id {range}");
sb.AppendLine($"Roll# {range}");
Instead of 1, use 2 StringBuilder instances:
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
sb1.Append("Id ");
sb2.Append("Roll# ");
for (int i = 0; i < 10; i++)
{
sb1.Append(i + " ");
sb2.Append(i + " ");
}
Console.WriteLine(sb1);
Console.WriteLine(sb2);
This will always require at least 3 loops:
One for the creation for the array.
One for each WriteLine.
At best you can have somebody elses code do the looping for you.
Unless you are interested in pulling stunts like manually inserting the Newline into a really long string, there is no way to save even a single loop. But such a thing is just unreliable and should not be atempted.
It honestly sounds a lot like a Speed Question, and for those we have the speed rant. You should read it either way, but can skip part 1.
The only improovement I can think of is building those strings with a stringbuilder. String concatenation in loops can be a bit troublesome. But on this scale it works either way.
The program must sum the even and odd numbers and then multiply them.
The problem comes when I enter the numbers like this 12345.
The array takes the number like 1 element but in order to make my code work it must separate the input when I put it like this 12345.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab_Methods
{
class Program
{
static void Main(string[] args)
{
int[] number = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
int even = 0;
int odd = 0;
for (int i = 0; i < number.Length; i++)
{
if (number[i] % 2 == 0)
{
even = even + number[i];
}
else
{
odd = odd + number[i];
}
}
Console.WriteLine(even * odd);
}
}
}
If you want to split on ' ' (space), your input should use delimiter: "1 2 3 4 5"
// Separated input like "1 2 3 45 6 789"
// we don't have to materialize into array
// let's be nice: allow tabulation as well as space,
// tolerate leading/trailing and double spaces: " 1 2 3 "
var numbers = Console
.ReadLine()
.Split(new char[] { ' ', '\t'}, StringSplitOptions.RemoveEmptyEntries) // let's be nice
.Select(item => int.Parse(item));
int even = 0;
int odd = 0;
foreach (var number in numbers) {
if (number % 2 != 0)
odd += number;
else
even += number;
}
Console.WriteLine(even * odd);
If you want to enumerate digits within single number (e.g. within "12345")
// Single number input like "12345678"
var numbers = Console
.ReadLine()
.Where(c => c >= '0' && c <= '9') // characters in '0'..'9' range
.Select(c => c - '0'); // corresponding ints
// Then as usual
int even = 0;
int odd = 0;
foreach (var number in numbers) {
if (number % 2 != 0)
odd += number;
else
even += number;
}
Console.WriteLine(even * odd);
This way you will be able to input numbers from 0 to 9 without having to care about the way they are written:
class Program
{
static void Main(string[] args)
{
int[] numbers = Console.ReadLine().Select(x => {
if(int.TryParse(x.ToString(), out int result))
{
return result;
}
else
{
return -1;
}
}).Where(x => x != -1).ToArray();
int even = 0;
int odd = 0;
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] % 2 == 0)
{
even = even + numbers[i];
}
else
{
odd = odd + numbers[i];
}
}
Console.WriteLine(even * odd);
}
}
Input:
12345
Output:
54
Input:
1 2 3 4 5
Output:
54
Input:
1,2,3,4,5
Output:
54
Input:
,1.2 34|5
Output:
54
The program should take in a parameter N and print out N + 1 lines.
I have to output something like this.
This is the output which I must get at N = 5
A //Increment by 0
AB //Increment by 1
ACE //Increment by 2
ADGJ //Increment by 3
AEIMQ //Increment by 4
The algorithm uses N as the number of characters to skip in between each add. So at N=3, it's A skip 3 to D, skip 3 to G, skip three to J.
And when the program runs out of upper case characters(i.e. When N is too big), it should start with lower case characters and if it runs out of lower case then it should again start with upper case and so on.
I am a novice to programming. And I dont really know where to start. I've been working around the loops for a while and still have no clue what-so-ever.
Here's another approach using a Char[], modulo, StringBuilder and a for-loop which increments by n for efficiency:
readonly static Char[] letters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();
static String appendChars(int n)
{
int length = n + 1;
StringBuilder sBuilder = new StringBuilder("A", length);
for (int i = n; sBuilder.Length < length; i += n)
{
Char nextChar = letters[i % letters.Length];
sBuilder.Append(nextChar);
}
return sBuilder.ToString();
}
test your sample data:
int n = 5;
IEnumerable<String> allWords = Enumerable.Range(0, n).Select(i => appendChars(i));
Console.Write(string.Join(Environment.NewLine, allWords));
outputs:
A
AB
ACE
ADGJ
AEIMQ
Here's the demo: http://ideone.com/0sspY
Try This :
public string GetOutPut(int increment)
{
string alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string output = string.Empty;
for(int i=0; i<=increment; i++)
{
int index = i*increment;
if(index>alphabets.Length)
index = index % alphabets.Length;
output+= alphabets[index];
}
return output;
}
It's not clear how you get the number of lines that you want - because you said N+1 but your example gives only N lines.
The following can be used to generate each one of those individual lines, and the Algo method can be modified to generate n+1 lines by sticking the code in a while loop, decrementing n and len and using AppendLine on the StringBuilder:
char[] allowedChars = Enumerable.Range('A', 26).Concat(Enumerable.Range('a', 26))
.Select(i => (char)i).ToArray();
[TestMethod]
public void Test()
{
Assert.AreEqual("A", Algo(0, 1));
Assert.AreEqual("AB", Algo(1, 2));
Assert.AreEqual("ACE", Algo(2, 3));
Assert.AreEqual("ADGJ", Algo(3, 4));
Assert.AreEqual("AEIMQ", Algo(4, 5));
}
public string Algo(int n, int len)
{
StringBuilder sb = new StringBuilder();
int nextCharIndex = 0;
for (int f = 0; f < len; f++)
{
sb.Append(allowedChars[nextCharIndex]);
//the `%`, or mod, here wraps around the next character back to upper case
nextCharIndex = (nextCharIndex + n) % allowedChars.Length;
}
return sb.ToString();
}