Skip to content

Instantly share code, notes, and snippets.

@elazar
Last active January 27, 2023 15:20
Show Gist options
  • Save elazar/6563802 to your computer and use it in GitHub Desktop.
Save elazar/6563802 to your computer and use it in GitHub Desktop.
Password Iterator vs GeneratorOriginal commented password iterator implementation: https://gist.github.com/elazar/1342491
<?php
function PasswordGenerator($min = 1, $max = null)
{
$ord = range(32, 126);
$chr = array_map('chr', $ord);
$first = reset($chr);
$last = end($chr);
$length = $min;
$password = array_fill(0, $length, $first);
$stop = array_fill(0, $length, $last);
$end = $length - 1;
while ($max ? $max >= $length : true) {
yield implode('', $password);
if ($password == $stop) {
$length++;
$password = array_fill(0, $length, $first);
$stop = array_fill(0, $length, $last);
$end = $length - 1;
} else {
for ($left = $end; isset($password[$left]) && $password[$left] == $last; $left--);
if (isset($password[$left]) && $password[$left] != $last) {
$password[$left] = $chr[array_search($password[$left], $chr) + 1];
for ($index = $left + 1; $index < $length; $index++) {
$password[$index] = $first;
}
}
}
}
}
<?php
class PasswordIterator implements Iterator
{
protected $length;
protected $min;
protected $max;
protected $counter;
protected $password;
protected $chr;
protected $ord;
protected $first;
protected $last;
protected $end;
protected $stop;
public function __construct($min = 1, $max = null)
{
$this->min = $min;
$this->max = $max;
$this->ord = range(32, 126);
$this->chr = array_map('chr', $this->ord);
$this->first = reset($this->chr);
$this->last = end($this->chr);
$this->rewind();
}
protected function increment()
{
$this->length++;
$this->password = array_fill(0, $this->length, $this->first);
$this->stop = array_fill(0, $this->length, $this->last);
$this->end = $this->length - 1;
}
public function rewind()
{
$this->length = $this->min - 1;
$this->counter = 1;
$this->increment();
}
public function current()
{
return implode('', $this->password);
}
public function key()
{
return $this->counter;
}
public function next()
{
$this->counter++;
if ($this->password == $this->stop) {
$this->increment();
} else {
for ($left = $this->end; isset($this->password[$left]) && $this->password[$left] == $this->last; $left--);
if (isset($this->password[$left]) && $this->password[$left] != $this->last) {
$this->password[$left] = $this->chr[array_search($this->password[$left], $this->chr) + 1];
for ($index = $left + 1; $index < $this->length; $index++) {
$this->password[$index] = $this->first;
}
}
}
}
public function valid()
{
return $this->max ? ($this->max >= $this->length) : true;
}
}
@elazar
Copy link
Author

elazar commented Jan 27, 2023

Wonder if this could feasibly be rewritten to use a recursive generator?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment