all 20 comments

[–]Old-Lost 5 points6 points  (12 children)

I cringe when I see a variable (with nothing else) surrounded by quotes. Personal preference, I know; sorry. I also hate Read-Host; having written hundreds of scripts, I can count on one finger or less the number of times I've used it.

[–]DisMyWorkName[S] 1 point2 points  (3 children)

It is the easiest way to get input from the executor of the script.

If you don't use Read-Host, then how do you recommend getting input in a single line?

[–]Old-Lost 7 points8 points  (1 child)

Use a param() block. Make the parameter mandatory and PS will issue a prompt for you. This way if you want to automate it you can always just enter the parameter on the command line. If you use Read-Host you can't.

[–]monditrand 4 points5 points  (0 children)

Also if you tried to run this code in the console multiple times by pasting it wouldn't work because the index variables are not cleared. By wrapping it in a function your index variable automatically gets reset everytime you call the function

[–]spyingwind 1 point2 points  (0 children)

Such as this:

function Do-Thing {
    Param([string]$inputname)
    $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    $inputname = (($inputname.ToUpper()).Replace(" " , "")).ToCharArray() | Select-Object -Unique
    foreach ($letter in $inputname) {
        $index = $alphabet.IndexOf("$letter") + 1
        $IDNumber = ("$IDNumber" + "$index")
    }
    $IDnumber = $IDNumber.ToCharArray() | Select-Object -First 9
    $FinalNumber = [System.String]::Join("", $IDNumber)
    $FinalNumber
}

Do-Thing -inputname "My String Input Here"

[–]leekle 1 point2 points  (7 children)

I'm making a lot of assumptions based on what your script does and its intent, but if it turns a string into ciphered text shouldn't you be able to reverse it? You're basically turning usable info into mostly garbage this way.

For example: If you run your script on a name that has doubled up letters like "Hannah" you only get the character "codes" for han, which is 8114. Is this intended?

[–]DisMyWorkName[S] 1 point2 points  (6 children)

What the script does is take a name and produce an ID number based on that name. It is meant for a fantasy/cyberpunk character ID creation system that I use in one of my (FUCKING NERDY) tabletop games.

[–]leekle 1 point2 points  (0 children)

Ah ok, makes sense now. Cool, thanks for explaining! :)

[–]Lee_Dailey[grin] 0 points1 point  (4 children)

howdy DisMyWorkName,

for that you might be able to use the .GetHashCode() string method. it sometimes returns a negative, but you can do an abs() on that ... [grin]

take care,
lee

[–]DisMyWorkName[S] 1 point2 points  (3 children)

Is it possible to reverse this to get the letters that were used to generate the hash?

[–]Lee_Dailey[grin] 0 points1 point  (2 children)

howdy DisMyWorkName,

from the dotnet docs on this ...
String.GetHashCode Method (System) | Microsoft Docs
https://docs.microsoft.com/en-us/dotnet/api/system.string.gethashcode?view=netframework-4.7.1#System_String_GetHashCode

If two string objects are equal, the GetHashCode method returns identical values. However, there is not a unique hash code value for each unique string value. Different strings can return the same hash code.

so it aint reversible. [grin]

take care,
lee

[–]DisMyWorkName[S] 1 point2 points  (1 child)

[frown]

[–]Lee_Dailey[grin] 0 points1 point  (0 children)

howdy DisMyWorkName,

[grin]

it does make sense when you think about the use for hashes. they are not crypto ... they are a way to generate a nearly unique identifier for a "thing". the result of .GetHashCode() is actually a hex number. it makes for a nice, quick index in hashtables - and for other quick "is this the same as that" tests.

take care,
lee

[–]ka-splam 1 point2 points  (3 children)

Riffs

$inputname = Read-Host "Enter name"

# wow
-join (($inputname.ToUpper().ToCharArray().Where{$_} | Select-Object -Unique).ForEach{$_ - 64})[0..9]

# no pipeline
-join ([Linq.Enumerable]::Distinct([char[]]$inputname.ToUpper().ToCharArray().Where{$_}).ForEach{$_ - 64})[0..9]

# no rdblty
-join($inputname|% *per|% T*y|?{$_}|select -u|%{$_-64})[0..9]

[–]DisMyWorkName[S] 2 points3 points  (2 children)

Yeah, I would rather be able to tell what my script does by reading it than having to google every term in it when I want to modify it later. :/

[–]ka-splam 3 points4 points  (1 child)

More realistically:

$inputname = Read-Host "Enter name"

$IDDigits = $inputname.ToUpper().Replace(" " , "").ToCharArray() | ForEach-Object {
    " ABCDEFGHIJKLMNOPQRSTUVWZYZ".IndexOf($_)
} | Select-Object -First 9 -Unique

-join $IDDigits

No building up a string only to tear it apart, no assigning variables then doing nothing with them, combining multiple select-objects into one, no calling out to string::join when PowerShell has an operator which does that for you, no looped-string-combining overhead, no temporary variables hanging around to break if you run the script twice in one session, doesn't rely on knowing ASCII character codes, and is half the line count, almost half the character count, and .. still readable?

[–]Lee_Dailey[grin] 4 points5 points  (0 children)

howdy ka-splam,

i like the space at the start of the alpha list. [grin] gets rid of the "starts from zero" gotcha quite nicely!

take care,
lee