Home > Software design >  How would you generate a unique sequence from 000 to 9ZZ
How would you generate a unique sequence from 000 to 9ZZ

Time:01-15

How would you generate a unique sequence from 000 to 9ZZ. Lastly, my export-csv is not working. Please see the data and export output below.

The alphanumeric sequence starts from 0 through 9 and then A through Z.

Please be advised, my PowerShell skill are a bit new. :)

$i = @()
$a = 0..9
$b = 65..90 | Foreach{[Char]$_}
$i = $a   $b
For($d = 0; $d -le $i.count; $d  ){
    $g = $i[$d]

    For($e = 0; $e -le $i.count; $e  ){
        $h = $i[$e]

        For($f = 0; $f -le $i.count; $f  ){
            $j = $i[$f]

            $k = "{0}{1}{2}" -f $g, $h, $j
            $k #| Export-Csv -Path .\List.csv -NoTypeInformation -Append

            If($k -eq '9ZZ'){
                Break
            }
        }
    }
}

Data Output:
000
001
.
.
|
V
009
00A
.
.
00Z
00 <-- I don't get this.
010

Export:
Length
3 <-- I don't get this either.
.
.
|
v
3

Any and all help is appreciated. Thank you in Advanced. ;)

CodePudding user response:

This is a classic off-by-1 error - your loops run from 0 through $i.count (included), which is exactly 1 longer than $i.

Change -le $i.count to -lt $i.count in all 3 loop conditions and it'll work.


You could simplify your code by generating the full range of digits/characters up front a little differently, and then use 3 nested foreach loops instead:

$digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.ToCharArray()

$ranges = 
  :outerLoop
  foreach($a in $digits){
    foreach($b in $digits){
      foreach($c in $digits){
        # save and output new value
        ($label = "${a}${b}${c}")
        # exit the label generation completely if we've reached the desired upper boundary
        if($label -eq '9ZZ'){ break outerLoop }
      }
    }
  }

$ranges now contain the correct range of labels from 000 through 9ZZ

CodePudding user response:

I would do it this way, with 3 foreach loops and a labeled break:

$digits = 0..9
$chars = (65..90).ForEach([char])
$dict = $digits   $chars

$result = :outer foreach($i in $dict)
{
   foreach($x in $dict)
   {
      foreach($z in $dict)
      {
         '{0}{1}{2}' -f $i,$x,$z
         if($i -eq 9 -and $x -eq 'Z' -and $z -eq 'Z')
         {
            break outer
         }
      }
   }
}

$result | Export-Csv ...

CodePudding user response:

To complement the helpful existing answers with a generalized solution for producing permutations of characters with a given number of places, using recursive helper function Get-Permutations:

function Get-Permutations {
  param(
    [Parameter(Mandatory)]
    [string] $Chars,        # e.g. '0123456789'
    [Parameter(Mandatory)]
    [uint] $NumPlaces       # e.g. 2, to produce '00', '01', ..., '99'
  )
  
  switch ($NumPlaces) {
    0 { return }
    1 { [string[]] $Chars.ToCharArray() }
    default {
      Get-Permutations -Chars $Chars -NumPlaces ($NumPlaces-1) | ForEach-Object {
        foreach ($c in $chars.ToCharArray()) { $_   $c }
      }
    }
  }
}

You'd call it as follows (to get '000', '001', ..., but all the way up to 'ZZZ' - you can post-filter with ... | Where-Object { $_ -le '9ZZ' })

Get-Permutations '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 3

Note:

  • In PowerShell (Core) 7 you can create the string of characters with
    -join ('0'..'9' 'A'..'Z')
  • In Windows PowerShell, where you cannot use [char] instances with the range operator, .., you can use the following, more concise alternative to your approach:
    -join ([char[]] (48..57) [char[]] (65..90)), based on the chars.' code points obtained with, e.g. [int] [char] 'A'

CodePudding user response:

similarly you could cheat since '009' -le '00A'

function inc([string]$s){
   [byte[]]$v = [char[]]$s
   $radix = $v.Count-1
   $carry = $true
   while($carry -and $radix -ge 0){
      switch(  $v[$radix]){
       91{$v[$radix] = 48}
       58{$v[$radix] = 65; $carry = $false}
       default{$carry = $false}
      }
      $radix--
   }
   $out = [char[]]$v -join ''
   $c = if($carry){'1'}else{''}
   return ($c   $out)
}

&{for($i = '000'; $i -le '9ZZ'; $i = inc $i){
   write-output $i
}} | set-content -Path .\List.csv
  •  Tags:  
  • Related