How to improve this C# code to count holes in numbers? [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I want to solve this puzzle with a more elegant code in C#.
using System;
public class Program
{
public static void Main()
{
int numero = 12345678;
int check = CountHoles(numero);
Console.WriteLine(check);
}
public static int CountHoles(int num){
int roles = 0;
for (int i=0; i < num.ToString().Length; i++ ){
string ver = "";
ver = num.ToString().Substring(i,1);
if (ver.Contains("0") || ver.Contains("4") || ver.Contains("6") || ver.Contains("9")){
roles++;
}
if (ver.Contains("8")){
roles = roles+2;
}
}
return roles;
}
}
.Net Fiddle: https://dotnetfiddle.net/3s8ucy
Thanks :)

I like to use dictionary maps in place of if-statements. You can use LINQ to get an array of digits from the string and then another LINQ statement to sum the results (or you can combine the two into a single LINQ statement).
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
private static Dictionary<int, int> _holeMap = new Dictionary<int, int>
{
{ 0, 1 },
{ 1, 0 },
{ 2, 0 },
{ 3, 0 },
{ 4, 1 },
{ 5, 0 },
{ 6, 1 },
{ 7, 0 },
{ 8, 2 },
{ 9, 1 }
};
public static void Main()
{
int numero = 12345678;
int check = CountHoles(numero);
Console.WriteLine(check);
}
public static int CountHoles(int num){
var digits = num
.ToString()
.Select(c => int.Parse(c.ToString()));
return digits.Sum(d => _holeMap[d]);
}
}
https://dotnetfiddle.net/gI5f02

You do not need to convert the number to string, you can improve method CountHoles like this:
int holes = 0;
do{
float tmp = (float) num / 10;
num /= 10;
int ver = (tmp - num) * 10;
if (ver == 0 || ver == 4 || ver == 6 || ver == 9) holes++;
if (ver == 8) holes += 2;
}while (num != 0)
return roles;

Related

I can't return the result and I can't get a value from the main function for function [closed]

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 2 years ago.
Improve this question
Question:
Have the function ClosestEnemy(arr) take the array of numbers stored in arr and from the position in the array where a 1 is, return the number of spaces either left or right you must move to reach an enemy which is represented by a 2. For example: if arr is [0, 0, 1, 0, 0, 2, 0, 2] then your program should return 3 because the closest enemy (2) is 3 spaces away from the 1. The array will contain any number of 0's and 2's, but only a single 1. It may not contain any 2's at all as well, where in that case your program should return a 0.
My problem Console.Readline() and return.I dont know proper use.
I get to this errors, I put a comment line on the code
CS1503 C# Argument 1: cannot convert from 'int' to 'int[]'
CS0165 C# Use of unassigned local variable 'result'
examples:
Input: new int[] {1, 0, 0, 0, 2, 2, 2}
Output: 4
Input: new int[] {2, 0, 0, 0, 2, 2, 1, 0}
Output: 1
public static int ClosestEnemy1(int[] arr)
{
int result;
int counterright = 0;
int counterleft = 0;
int locationleft = 0;
int location1 = 0;
int locationright = 0;
int rightclosest;
int leftclosest;
int i;
// code goes here
for(i = 0; i < arr.Length; i++)
{
if (arr[i] == 1)
{
location1 = i;//1'in konumu belirlendi
}
}
//sağa kontrol et
while (arr[i]!= '\0' )//saga bak
{
i = location1;
i++;
if (arr[i] == 2)
{
counterright = 1;
locationright = i;
break;
}
}
for (i = location1; i >= 0; i--)
{
if (arr[i] == 2)
{
counterleft = 1;
locationleft = i;
break;
}
}
if(counterright == 0 && counterleft == 0)
{
result=0;
}
if(counterright == 0 && counterleft == 1)
{
result = location1 - locationleft;
}
if(counterright == 1 && counterleft == 0)
{
result = locationright - location1;
}
if(counterright == 1 && counterleft == 1)
{
leftclosest = location1 - locationleft;
rightclosest = locationright - location1;
if (leftclosest > rightclosest)
{
result = leftclosest;
}
else
{
result= rightclosest;
}
}
return result; //it's error!!!!!!!
}
static void Main()
{
// keep this function call here
Console.WriteLine(ClosestEnemy1(Convert.ToInt32(Console.ReadLine())));//it's errorr!!!!
}
Try these corrections in your code:
1) chnage input type to string : public static int ClosestEnemy1(string inputString)
, make sure you leave the comment for user to enter input like this: 1, 0, 0, 0, 2, 2, 2
2) inside the function make int arr[] by String.Split():
string[] stringNumbers = inputString .Split(',');
int[] arr = Array.ConvertAll(stringNumbers, s => int.Parse(s));
3) change this line :
int result=0; to assign the default value to result .
4) assign i=0 or what you think better before while, becuse the last assigned value for i is 7 and it will has an error.
//sağa kontrol et
i = 0;
while (arr[i] != '\0')//saga bak
5) in the main() function after you get console result, put a Console.ReadKey(); to you see the result.

remove sequential numbers from int array / int list [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
im generating a list of numbers such as 100 101 102 103 110 111 112 130 131 132 and i want to remove numbers that are sequential till the next number but with a specific tolerance...
so with a tolerance of 3 for example my output will be
100 102
110 112
130 132
the tolerance value must be adjustable...
ADRS is my list of int's,
ADRSC is my list of strings after being cleaned
for (int v = 0; v <= ADRS.Count - 2; v++)
{
if (v == 0) //adds first number
ADRSC.Add(ADRS[v].ToString());
if (ADRS[v]-(int.Parse(ADRSC.Last())) > 3)
{
ADRSC.Add(ADRS[v].ToString());
}
}
in short:
i want to remove the numbers inbetween, that have a difference of under 3
This worked
adrCache = Nums.First();
for (int x=1; x < Nums.Count-2; x++)
{
if ((Nums[x+1] - adrCache) <= 4)
{
adrCache = Nums[x+1];
Nums[x] = 0; //ill then just remove all zeros
}
else {
adrCache = Nums[x];
}
}
Here's a shot at what you're looking for, but the question is a little unclear to me:
public static List<int> RemoveSequential(List<int> items, int tolerance)
{
if (items == null || items.Count < 2) return items;
var result = new List<int> {items.First()};
var sequenceCount = 0;
for(int i = 1; i < items.Count; i++)
{
if (Math.Abs(items[i] - items[i - 1]) == 1)
{
sequenceCount++;
if (sequenceCount == tolerance - 1)
{
result.Add(items[i]);
}
}
else
{
sequenceCount = 0;
result.Add(items[i]);
}
}
return result;
}
Usage would look like:
public static void Main(string[] args)
{
var input = new List<int> {100, 101, 102, 103, 110, 111, 112, 130, 131, 132};
var output = RemoveSequential(input, 3);
Console.WriteLine($"Input: {string.Join(", ", input)}");
Console.WriteLine($"Output: {string.Join(", ", output)}");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output

Divide The Deck In Two Players

I want to give even number cards to player 1 and odd number cards to player 2 . If any of you guys could do it that will be really appreciated thank you. I know how to do this with array, but I am not sure with list.
class MatchDeck
{
private const int NUMBER_OF_CARDS = 36;
private Random r = new Random();
List<MatchCard> deck = new List<MatchCard>();
public MatchDeck(){ }
public void createDeck()
{
int[] number = { 2, 3, 4, 5, 6, 7, 8, 9, 10 };
string[] suits = { "R[]", "R0", "B0", "B[]" };//these are suits i just made up
// deck = new MatchCard[NUMBER_OF_CARDS];
foreach (var suit in suits)
{
for (int num = 2; num <= 10; num++)
{
deck.Add(new MatchCard(num, suit));
// Console.WriteLine(deck[i++].toString());
}
}
foreach(MatchCard card in deck)
{
Console.WriteLine(card.Number + " " + card.Suit);
}
}
public void Shuffle()
{
Random ran = new Random();
int n = deck.Count;
while (n > 1)
{
n--;
int k = ran.Next(n + 1);
MatchCard value = deck[k];
deck[k] = deck[n];
deck[n] = value;
}
foreach (MatchCard card in deck)
{
Console.WriteLine(card.Number + " " + card.Suit);
}
}
public void deal()
{
List<MatchCard> player1 = new List<MatchCard>();
List<MatchCard> player2 = new List<MatchCard>();
}
}
What you trying to achieve can be done by using a loop or Linq.
If you want to loop through your array or List the condition would be
if(deck[i] % 2 == 0) for even numbers. The opposite for odd. But this is already mentioned in the comment of #misha130.
May be you want to read about the Linq possibilities that List offers.
Here is a post that gives you a nice example how to extract values from a List according to a condition (like in your case). To get to know the class List and its methods please read the documentation
These two particular methods would be of your main interest in this case: FindAll && Where
Now you should have all the necessary information to solve your problem. Good luck. Comment if you are still stuck.
I've refactored your code so to what you're after. The key part relating to dealing the cards is the .Where((x, n) => n % 2 == 0)& .Where((x, n) => n % 2 == 1) code.
public class MatchDeck
{
private Random r = new Random();
List<MatchCard> deck = null;
public MatchDeck()
{
int[] number = { 2, 3, 4, 5, 6, 7, 8, 9, 10 };
string[] suits = { "R[]", "R0", "B0", "B[]" };
deck = number.SelectMany(n => suits, (n, s) => new MatchCard(n, s)).ToList();
}
public void Shuffle()
{
deck = deck.OrderBy(x => r.Next()).ToList();
}
public void Deal()
{
List<MatchCard> player1 = deck.Where((x, n) => n % 2 == 0).ToList();
List<MatchCard> player2 = deck.Where((x, n) => n % 1 == 0).ToList();
}
}

How to find successive numbers in a List<int> with duplicates?

I was bored so I decided to try & make a Yahtzee game of my own, same exact rules as the actual game, just wanted to test my programming skills on this (which aren't amazing as of yet).
The code posted below is being used to check for straights (both Small & Large).
I'm sure you can see for yourself, but just in case you don't, it works like this:
All 5 dice's values are placed in a List, which are then sorted using the List<T>.Sort() method.
Now they should be sorted in the list, in ascending order (for example 1,2,3,4,5).
In order to find out if it's a large straight, I simply use an int which adds 1 to it's value if a small straight is detected, a large straight is then found due to my "Large Straight = Small Straight * 2" logic, which may be flawed, but it seems to make sense to me :) .
This works, but not always, as you can probably see, this code won't work if I have duplicate values somewhere in the middle, for example 1,2,3,3,4,6. This series of numbers should still give me a small straight, but it won't.
Now as for my actual question: How do I modify this code so it'll always detect both small & large straights?
List<int> valList = new List<int>();
foreach (Dice d in dList)
{
valList.Add(d.Value);
}
valList.Sort();
txtSmall.Text = "0";
txtLarge.Text = "0";
int straight = 0;
if (valList[0] == valList[1] - 1 && valList[1] == valList[2] - 1 && valList[2] == valList[3] - 1)
straight++;
if (valList[1] == valList[2] - 1 && valList[2] == valList[3] - 1 && valList[3] == valList[4] - 1)
straight++;
switch (straight)
{
case 1:
if (txtSmall.IsEnabled)
txtSmall.Text = "30";
break;
case 2:
if (txtSmall.IsEnabled)
txtSmall.Text = "30";
if (txtLarge.IsEnabled)
txtLarge.Text = "40";
break;
}
PS: Just in case you need to know how I have my Dice class, here it is (even though I can't see why you would have need of it):
class Dice
{
private static CryptoRandom r = new CryptoRandom();
public static int uBound = 1;
public static int lBound = 7;
public string Path { get; set; }
private int value;
public int Value
{
get { return value; }
}
private bool locked;
public bool Locked
{
get { return locked; }
}
public Dice(int lowerBound = 1, int upperBound = 6)
{
uBound = upperBound + 1;
lBound = lowerBound;
this.Roll();
this.locked = false;
}
public void Roll()
{
this.value = r.Next(lBound, uBound);
}
public void Lock()
{
this.locked = true;
}
public void Unlock()
{
this.locked = false;
}
}
PPS: If there's a better way to detect these things, feel free to share, however try to answer my question as well :).
If performance is not an issue and I understand the problem correctly I would try something like this:
var count = dList.Count; //6
var straights = dList.Select(dice => dice.Value)
.Distinct() //5,3,1,6,4
.OrderBy(dice => dice.Value) //1,3,4,5,6
.Select(dice => dice.Value + (count--)) //7,8,8,8,8
.GroupBy(n => n) //[7,{7}],[8,{8,8,8,8}]
.OrderByDecending(group => group.Count());
var longestStraight = straights.First().Count(); //4
A really simple way is to just invoke Distinct before you sort it, which removes all duplicates:
List<int> allDice = new List<int>() { 1, 2, 3, 3, 4, 6 };
IEnumerable<int> uniqueDice = allDice.Distinct();
IEnumerable<int> sortedDice = uniqueDice.Sort(x => x);
//etc.
Otherwise, your methodology is reasonable. Nothing comes quickly to mind as a better way to find a small straight.
Here's another way to do it, just for fun:
/// <summary>
/// Determines if the dice passed in contain a strait
/// </summary>
/// <param name="dice">The dice to test</param>
/// <returns>0 if there are no straits, 1 if there is a small strait,
/// or 2 if it contains both a large and small strait</returns>
private static int ContainsStrait(IEnumerable<int> dice)
{
var uniqueDice = dice.Distinct().ToList();
if (uniqueDice.Count < 4) return 0;
uniqueDice.Sort();
int consecutiveNumbers = 1;
int lastValue = -1;
foreach (var uniqueDie in uniqueDice)
{
if (uniqueDie == lastValue + 1)
{
consecutiveNumbers++;
}
else
{
consecutiveNumbers = 1;
}
lastValue = uniqueDie;
}
return (consecutiveNumbers > 4) ? 2 : (consecutiveNumbers > 3) ? 1 : 0;
}
To test it:
private static void Main()
{
var rolls = new List<List<int>>
{
{new List<int> {3, 3, 3, 3, 3, 3}},
{new List<int> {1, 2, 3, 4, 3, 2}},
{new List<int> {2, 2, 3, 4, 5, 2}},
{new List<int> {3, 3, 3, 4, 5, 6}},
{new List<int> {1, 2, 3, 4, 5, 2}},
{new List<int> {2, 2, 3, 4, 5, 6}}
};
foreach (var roll in rolls)
{
int result = ContainsStrait(roll);
Console.WriteLine("The roll: {0} does {1}contain a small strait {2} a large strait",
string.Join(", ", roll),
result > 0 ? "" : "not ",
result == 2 ? "and" : result == 1 ? "but not" : "or");
}
}
Why not put the dices in an array?
int Sum = 0;
int[] i = new int[5];
Problem here is, if we have doubles, we must move them to the end of the array.
Array.Sort(i);
for( int j = 0; j < 4; j++ )
{
int temp = 0;
if( i[j] == i[j+1] )
{
temp = i[j];
for( int k = j; k < 4; k++ )
{
i[k] = i[k+1];
}
i[4] = temp;
}
}
When that is done, it's simply a matter of evaluation
if( ((i[0] == 1) && (i[1] == 2) && (i[2] == 3) && (i[3] == 4)) ||
((i[0] == 2) && (i[1] == 3) && (i[2] == 4) && (i[3] == 5)) ||
((i[0] == 3) && (i[1] == 4) && (i[2] == 5) && (i[3] == 6)) ||
((i[1] == 1) && (i[2] == 2) && (i[3] == 3) && (i[4] == 4)) ||
((i[1] == 2) && (i[2] == 3) && (i[3] == 4) && (i[4] == 5)) ||
((i[1] == 3) && (i[2] == 4) && (i[3] == 5) && (i[4] == 6)) )
{
Sum = 30;
}
And for a large straight, it's even easier :
Array.Sort(i)
if( (i[0]+1 == i[1]) && (i[0]+2 == i[2]) && (i[0]+3 == i[3]) && (i[0]+4 == i[4]) )
{
Sum = 40;
}

C# print every third number!

Help needed to perform an output in C# console application.
I have a maximum number
int maxNr = 10;
int myValue = 1;
public void myMethod(){
int choice = int.Parse(Console.ReadLine()); // only 1 or 2 accepted.
//Only choice = 1 in displayed here.
if(choice == 1){
while(myValue <= maxNr){
Console.WriteLine(myValue);
myValue = myValue + 3;
}
}
}
Expected output:
1, 4, 7, 10
Next time the function is called the output should be:
3, 6, 9
2, 5, 8
myValue is stuck at 13 after the first call, so the code does not enter the loop the second time
Add this before the while loop:
if (myValue >= 10)
myValue -= 10;
Edit:
1.If I understood you correctly, the expected output is:
1st call 1, 4, 7, 10.
2nd call: 3, 6, 9.
3rd call 2, 5, 8.
2.As some suggested, you should use for loop instead of while loops:
if (myValue >= maxNr)
myValue -= maxNr;
for (; myValue <= maxNr; myValue += 3)
{
Console.WriteLine(myValue);
}
for (i=0; i<n; i+=3) don't work for you?
Why not just use this?
for (int i = n; i <= maxNr; i = i+3) {
Console.WriteLine(i);
}
myValue is not defined locally, so you need to set it to 0, when calling the method again, otherwise it would still be 10 and you do not enter the loop.
public void myMethod(){
int choice = int.Parse(Console.ReadLine()); // only 1 or 2 accepted.
int maxNr = 10;
int myValue = choice;
//Only choice = 1 in displayed here.
if(choice == 1){
while(myValue <= maxNr){
Console.WriteLine(myValue);
myValue = myValue + 3;
}
}
}
Reset your starting value each time.
You need to store myValue in a temporary variable and update it before exiting the method. As I understand your requirements the code to achieve the output is as given below,
static int maxNr = 10;
static int myValue = 1;
private static void Test()
{
int lastValue = myValue;
int choice = int.Parse(Console.ReadLine()); // only 1 or 2 accepted.
//Only choice = 1 in displayed here.
if (choice == 1)
{
while (myValue <= maxNr)
{
Console.WriteLine(myValue);
myValue = myValue + 3;
}
}
if (lastValue == 1)
{
myValue = lastValue + 3 - 1;
}
else
{
myValue = lastValue - 1;
}
}
Method Call
static void Main(string[] args)
{
Test();
Test();
Test();
Console.ReadLine();
}
Output
1
4
7
10
3
6
9
2
5
8
Note that the user needs to enter the value 1 at every function call.

Categories