C
C#2y ago
uselessxp

❔ ✅ is it possible to ''lock'' a var after the first assignment?

I'm making some base practice with C# with some exercises. I completed the first one, and it have a second part that ask an additional answer. Here's the code:
/*
Part 1

Santa is trying to deliver presents in a large apartment building, but he can't find the right floor - the directions he got are a little confusing. He starts on the ground floor (floor 0) and then follows the instructions one character at a time.

An opening parenthesis, (, means he should go up one floor, and a closing parenthesis, ), means he should go down one floor.
*/


/*
Part 2

Now, given the same instructions, find the position of the first character that causes him to enter the basement (floor -1). The first character in the instructions has position 1, the second character has position 2, and so on.
*/

using System.Text;

namespace AOC_2015_1
{
internal class DayOnePartTwo
{
static void Main(string[] args)
{
string? input;
Console.WriteLine("Where should I delivery the next gift?");
Console.SetIn(new StreamReader(Console.OpenStandardInput(), Encoding.UTF8, false, 8192));
input = Console.ReadLine();
Console.WriteLine($"Final floor is {GiftDelivery(input)}");
}

static short GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
int i = 0;
int x = 0;

foreach (char c in input)
{
if (floor == -1)
{
x = i;
Console.WriteLine("is " + x);
}
if (c == floorUpChar)
{
floor++;
i++;
}
else if (c == floorDownChar)
{
floor--;
i++;
}
}
return floor;
}
}
}
/*
Part 1

Santa is trying to deliver presents in a large apartment building, but he can't find the right floor - the directions he got are a little confusing. He starts on the ground floor (floor 0) and then follows the instructions one character at a time.

An opening parenthesis, (, means he should go up one floor, and a closing parenthesis, ), means he should go down one floor.
*/


/*
Part 2

Now, given the same instructions, find the position of the first character that causes him to enter the basement (floor -1). The first character in the instructions has position 1, the second character has position 2, and so on.
*/

using System.Text;

namespace AOC_2015_1
{
internal class DayOnePartTwo
{
static void Main(string[] args)
{
string? input;
Console.WriteLine("Where should I delivery the next gift?");
Console.SetIn(new StreamReader(Console.OpenStandardInput(), Encoding.UTF8, false, 8192));
input = Console.ReadLine();
Console.WriteLine($"Final floor is {GiftDelivery(input)}");
}

static short GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
int i = 0;
int x = 0;

foreach (char c in input)
{
if (floor == -1)
{
x = i;
Console.WriteLine("is " + x);
}
if (c == floorUpChar)
{
floor++;
i++;
}
else if (c == floorDownChar)
{
floor--;
i++;
}
}
return floor;
}
}
}
65 Replies
uselessxp
uselessxp2y ago
I'm not sure that in the second part it wants both answers, I mean including the answer of the first step, but I'd like to make it in this way for learn better. I know that consts wont work since it can be assigned only while declaration. Also ass the x value to i wont work since it will change every time until the cycle is not end, and it will print the last one, and the exercise want to know the first one. And I can't even stop the cycle when I get -1 value, since it's necessary for give in output the first answer. The only solution I actually thought functional is to use an array for collecting all values, and then just printing the first one putted in, but I don't know if is a legit way to achieve it^^
ero
ero2y ago
public static (int, int) GiftDelivery(string input)
{
const char FLOOR_UP = '(', FLOOR_DOWN = ')';
int floor = 0, basement = -1; // unset

for (int i = 0; i < input.Length; i++)
{
char c = input[i];

if (c is FLOOR_UP)
{
floor++;
}
else if (c is FLOOR_DOWN)
{
floor--;
}

if (basement == -1 && floor < 0)
{
basement = i + 1;
}
}

return (floor, basement);
}
public static (int, int) GiftDelivery(string input)
{
const char FLOOR_UP = '(', FLOOR_DOWN = ')';
int floor = 0, basement = -1; // unset

for (int i = 0; i < input.Length; i++)
{
char c = input[i];

if (c is FLOOR_UP)
{
floor++;
}
else if (c is FLOOR_DOWN)
{
floor--;
}

if (basement == -1 && floor < 0)
{
basement = i + 1;
}
}

return (floor, basement);
}
uselessxp
uselessxp2y ago
static short GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
int i = 0;
int x = 0; //for the cycle
int[] myarray = { 0,0,0,0,0,0 };

foreach (char c in input)
{
if (floor == -1)
{
myarray[x] = i;
x++;
}
if (c == floorUpChar)
{
floor++;
i++;
}
else if (c == floorDownChar)
{
floor--;
i++;
}
}
Console.WriteLine($"The first time when you get -1 is at position {myarray[0]}");
return floor;
}
static short GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
int i = 0;
int x = 0; //for the cycle
int[] myarray = { 0,0,0,0,0,0 };

foreach (char c in input)
{
if (floor == -1)
{
myarray[x] = i;
x++;
}
if (c == floorUpChar)
{
floor++;
i++;
}
else if (c == floorDownChar)
{
floor--;
i++;
}
}
Console.WriteLine($"The first time when you get -1 is at position {myarray[0]}");
return floor;
}
this seems work, I can improve it by not using an array but another collection items that doesn't require a fixed amount of items, so I don't have to put in some random values. it will remain the fact that I'll use it for store multiple values also when I just need the first one. I don't understand what the last if do. Also basement is never affected by the cycle. If I'm not wrong, in this way you'll print the last -1 position, instead printing the first one.
ero
ero2y ago
that's exactly what the if prevents only set basement if it has never been set before
uselessxp
uselessxp2y ago
oh right right definitely more clear than my solution I thought to improve this replacing the array with an arraylist but your solution seems more clean isn't better to define int vars as short in order to consume less resources?
uselessxp
uselessxp2y ago
and btw why the second way to declare an ArrayList is flagged as recommended? it doesn't explain why.
uselessxp
uselessxp2y ago
Console.WriteLine($"Final floor is {GiftDelivery(input)} and the first time when Santa enter the basement is {GiftDelivery(input)}");
Console.WriteLine($"Final floor is {GiftDelivery(input)} and the first time when Santa enter the basement is {GiftDelivery(input)}");
is there a way to select which parameter I want to get and print? in this way it print both since the called function return 2 parameters
uselessxp
uselessxp2y ago
Console.WriteLine(GiftDelivery(input).Item1);
Console.WriteLine(GiftDelivery(input).Item2);
Console.WriteLine(GiftDelivery(input).Item1);
Console.WriteLine(GiftDelivery(input).Item2);
Solved using this
uselessxp
uselessxp2y ago
Last question, I think, I wanted to proceed with ArrayList first as an update of my version, before go with your solution that's better. I noticed that if I never go to floor -1, the ArrayList will stay empty, and the program will crash. I could resolve it in 2 ways, at least I thought just those 2: 1) putting a random value into it for avoid making it empty (sounds like dirty xD) 2) using Try Catch statement for handle this exception Do you suggest to use one of those solutions, or you have a third one?
ero
ero2y ago
don't use arraylist it's a relic of literal decades ago
uselessxp
uselessxp2y ago
yeah I know that in this case is a bad choice. is also discontinued?
ero
ero2y ago
it's a bad choice in every case
uselessxp
uselessxp2y ago
I mean old and not used anymore
ero
ero2y ago
it's not generic, therefore not type safe
uselessxp
uselessxp2y ago
which collection should I use when I need to use something like ArrayList?
uselessxp
uselessxp2y ago
I tried this just for make practice, and I'm not understanding why it execute this instruction twice
ero
ero2y ago
you either use an array, or a list
uselessxp
uselessxp2y ago
ok I can't use
return (floor, "never");
return (floor, "never");
instead of
return (floor, 0);
return (floor, 0);
cause the function is setted to return two short values, so I suppose that if I want to print never I should put an if statement to the calling instruction like if second parameter == 0 print that santa never accessed the basement else print the value or is there some cool trick I don't know?
Anton
Anton2y ago
null
uselessxp
uselessxp2y ago
it seems I can't put those instruction in a ternary operator
Anton
Anton2y ago
$tryparse
MODiX
MODiX2y ago
The TryParse pattern is considered best practice of parsing data from a string: - a TryParse method returns true or false to inform you if it succeeded or not, so you can use it directly in a condition, - since C# 7 you can declare a variable that will be used as an out argument inline in an argument list, - it forces you to check if the out argument contains valid data afterwards, Avoid: Convert.ToInt32 — it's a bad choice for parsing an int. It exists only for backwards compatibility reasons and should be considered last resort.
return Convert.ToInt32(null); //returns 0. null should not be considered as 0 ever
return Convert.ToInt32("asdf"); //throws FormatException
return Convert.ToInt32(null); //returns 0. null should not be considered as 0 ever
return Convert.ToInt32("asdf"); //throws FormatException
(Note: Convert does contain useful conversion methods: To/FromBase64String, To/FromHexString, ToString(X value, int toBase), ToX(string? value, int fromBase)) Avoid: int.Parse — you have to use a try/catch statement to handle invalid input, which is a less clean solution.
var number = int.Parse("abc"); //throws FormatException
var number = int.Parse(""); //throws FormatException
var number = int.Parse("abc"); //throws FormatException
var number = int.Parse(""); //throws FormatException
Use int.TryParse https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=net-5.0#System_Int32_TryParse_System_String_System_Int32__
if (int.TryParse(someInput, out var result))
{
Console.WriteLine($"Thanks for giving me the following number: {result}!");
}
else
{
Console.WriteLine("You didn't give me a valid number :c");
}
if (int.TryParse(someInput, out var result))
{
Console.WriteLine($"Thanks for giving me the following number: {result}!");
}
else
{
Console.WriteLine("You didn't give me a valid number :c");
}
Int32.TryParse Method (System)
Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the operation succeeded.
Anton
Anton2y ago
read the docs on tuple types
uselessxp
uselessxp2y ago
much much better, I had to make this before xD
if (Convert.ToInt32(GiftDelivery(input).Item2) == 1337) Console.WriteLine($"Final floor is {GiftDelivery(input).Item1} and Santa never entered the basement");
else Console.WriteLine($"Final floor is {GiftDelivery(input).Item1} and the first time when Santa enter the basement is {GiftDelivery(input).Item2}");
if (Convert.ToInt32(GiftDelivery(input).Item2) == 1337) Console.WriteLine($"Final floor is {GiftDelivery(input).Item1} and Santa never entered the basement");
else Console.WriteLine($"Final floor is {GiftDelivery(input).Item1} and the first time when Santa enter the basement is {GiftDelivery(input).Item2}");
Anton
Anton2y ago
wtf
uselessxp
uselessxp2y ago
yeah it came from this
static (short, object) GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
short x = 0; //for the cycle
short y = 0; //for the basement check
var basement = new ArrayList();

foreach (char c in input)
{
if (floor == -1)
{
basement.Add(y);
x++;
}
if (c == floorUpChar)
{
floor++;
y++;
}
else if (c == floorDownChar)
{
floor--;
y++;
}
}
try
{
return (floor, basement[0]);
}
catch (System.ArgumentOutOfRangeException)
{
return (floor, 1337);
}
}
static (short, object) GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
short x = 0; //for the cycle
short y = 0; //for the basement check
var basement = new ArrayList();

foreach (char c in input)
{
if (floor == -1)
{
basement.Add(y);
x++;
}
if (c == floorUpChar)
{
floor++;
y++;
}
else if (c == floorDownChar)
{
floor--;
y++;
}
}
try
{
return (floor, basement[0]);
}
catch (System.ArgumentOutOfRangeException)
{
return (floor, 1337);
}
}
and I was unable to make the comparation with == with an object, so I had to convert it to Int32 first with null isn't necessary
uselessxp
uselessxp2y ago
in the meanwhile the compiler keep throwing null warnings xD, which is the severity of those warniings?
uselessxp
uselessxp2y ago
using System.Collections;
using System.Text;

namespace AOC_2015_1
{
internal class DayOnePartTwo
{
static void Main(string[] args)
{
string? input;
Console.WriteLine("Where should I delivery the next gift?");
Console.SetIn(new StreamReader(Console.OpenStandardInput(), Encoding.UTF8, false, 8192));
input = Console.ReadLine();
if (GiftDelivery(input!).Item2 == null) Console.WriteLine($"Final floor is {GiftDelivery(input!).Item1} and Santa never entered the basement");
else Console.WriteLine($"Final floor is {GiftDelivery(input!).Item1} and the first time when Santa enter the basement is {GiftDelivery(input!).Item2}");
}

static (short, object) GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
short x = 0; //for the cycle
short y = 0; //for the basement check
var basement = new ArrayList();

foreach (char c in input)
{
if (floor == -1)
{
basement.Add(y);
x++;
}
if (c == floorUpChar)
{
floor++;
y++;
}
else if (c == floorDownChar)
{
floor--;
y++;
}
}
try
{
return (floor, basement[0]!);
}
catch (System.ArgumentOutOfRangeException)
{
return (floor, null!);
}
}
}
}
using System.Collections;
using System.Text;

namespace AOC_2015_1
{
internal class DayOnePartTwo
{
static void Main(string[] args)
{
string? input;
Console.WriteLine("Where should I delivery the next gift?");
Console.SetIn(new StreamReader(Console.OpenStandardInput(), Encoding.UTF8, false, 8192));
input = Console.ReadLine();
if (GiftDelivery(input!).Item2 == null) Console.WriteLine($"Final floor is {GiftDelivery(input!).Item1} and Santa never entered the basement");
else Console.WriteLine($"Final floor is {GiftDelivery(input!).Item1} and the first time when Santa enter the basement is {GiftDelivery(input!).Item2}");
}

static (short, object) GiftDelivery(string input)
{
short floor = 0;
const char floorUpChar = '(';
const char floorDownChar = ')';
short x = 0; //for the cycle
short y = 0; //for the basement check
var basement = new ArrayList();

foreach (char c in input)
{
if (floor == -1)
{
basement.Add(y);
x++;
}
if (c == floorUpChar)
{
floor++;
y++;
}
else if (c == floorDownChar)
{
floor--;
y++;
}
}
try
{
return (floor, basement[0]!);
}
catch (System.ArgumentOutOfRangeException)
{
return (floor, null!);
}
}
}
}
I "solved" all null related warnings by putting a ! at the end of some parameters, but idk if I made a good thing or is maybe leave them as before and ignore warnings. the app seems working normal xD
Anton
Anton2y ago
object? are you serious null forgiving? lol you've got to be kidding learn nullability or disable it bro don't hack it like that
uselessxp
uselessxp2y ago
I putted object instead of short due to the ArrayList
Anton
Anton2y ago
ArrayList??? wtf are you doing? it's not the year 2000 List<string> is what you want ArrayList ignores the tyoe system
uselessxp
uselessxp2y ago
I used it to intercept at which position the floor had value -1 for the first time I started with an array, then I replaced it with an arraylist for improve the code, but now I'm assuming it's quite old what about this? null forgiving is what I made putting the ! everywhere ?
Anton
Anton2y ago
or List<whatever> yes that's the null forgiving operator
uselessxp
uselessxp2y ago
oh, I thought I was solving problems with it, so it's better I remove them ignoring the warnings
Anton
Anton2y ago
bruh either learn how nullability works or disable the nullability entirely
uselessxp
uselessxp2y ago
ok
ero
ero2y ago
like already mentioned in the code review the other day, nullability warnings are there for you to handle them not to ignore them
uselessxp
uselessxp2y ago
what about in the var declarations? I declared a var using
string? input;
string? input;
putting the ? at the end, I seen expert coders making this for remove the warning
ero
ero2y ago
string? input = Console.ReadLine();
if (input is null)
{
Console.WriteLine("Input is invalid.");
return;
}
string? input = Console.ReadLine();
if (input is null)
{
Console.WriteLine("Input is invalid.");
return;
}
all code below the if block will now know that input is not null because it can't be because you already handled the case where it is null
uselessxp
uselessxp2y ago
oh ok now I und, seems to be an easy concept the compiler just warn me that I didn't handled the nullability
uselessxp
uselessxp2y ago
Can I retain this valid for C#? Standing to this description, the List doesn't allow to add data dynamically, that's why I used ArrayList before on my program. I made some searches of other collections, but I didn't found anything that allow me do create a dynamic array. Stack and Queue could works for this job maybe. Btw I'll continue with my exercises for learn new things, and I think that I'll going to try learn Interfaces soon.
ero
ero2y ago
this is bogus what the fuck this is Java!
uselessxp
uselessxp2y ago
ik
ero
ero2y ago
so what are you doing reading this!
uselessxp
uselessxp2y ago
is the only comparison table I found on the web, for this I asked if is valid also for C# 🥲
ero
ero2y ago
i mean you have to specify that it's talking about java in the first place
uselessxp
uselessxp2y ago
yeah my bad
ero
ero2y ago
no, this is not at all true for c#
MODiX
MODiX2y ago
Ero#1111
REPL Result: Success
List<int> foo = new();
foo.Add(1);
foo.Add(2);
foo.Add(3);

foo
List<int> foo = new();
foo.Add(1);
foo.Add(2);
foo.Add(3);

foo
Result: List<int>
[
1,
2,
3
]
[
1,
2,
3
]
Compile: 443.184ms | Execution: 25.501ms | React with ❌ to remove this embed.
uselessxp
uselessxp2y ago
works really good^^
uselessxp
uselessxp2y ago
in this case I suppose that I should put a random number instead of null, since it's a valid value for numbers types
ero
ero2y ago
You shouldn't use try catch first of all
uselessxp
uselessxp2y ago
I put it for handle the empty case, the program crash normally
ero
ero2y ago
So handle the empty case Check if the list is empty or not
uselessxp
uselessxp2y ago
why is better to use an if statement instead of a try catch?
ero
ero2y ago
Way more performant, way more readable, way less prone to other issues
uselessxp
uselessxp2y ago
oh, ok, I thought it was more accurate for the purpose
ero
ero2y ago
what makes you say that? how much more accurate than if (basement.Count != 0) can you get?
uselessxp
uselessxp2y ago
I thought having the exact name of the exception and using a dedicated statement would be better
uselessxp
uselessxp2y ago
normally I would have declared the list using the second sample. is the first one a sort of abbreviation for creating new instances?
Anton
Anton2y ago
yes
uselessxp
uselessxp2y ago
it should be almost done. for some reason I'm trying to figure out, this get executed three times
uselessxp
uselessxp2y ago
I'm looking for var values and for some problem seems related to the whole foreach cycle that restart after all c in input are iterated
Monsieur Wholesome
I am going to throw up
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.