Skip to content

Instantly share code, notes, and snippets.

@TheRealJAG
Last active September 23, 2019 02:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save TheRealJAG/0acc8b81be8012f14a6b58808a0de26d to your computer and use it in GitHub Desktop.
Save TheRealJAG/0acc8b81be8012f14a6b58808a0de26d to your computer and use it in GitHub Desktop.
Write a function that provides change directory (cd) function for an abstract file system.
<?php
class Path {
public $currentPath;
function __construct($path) {
$this->currentPath = $path;
}
public function cd($newPath) {
$innerCounter = 0;
$strOut= '';
$newPath = explode('/',$newPath);
$oldPath = explode('/', $this->currentPath);
foreach($newPath as $str) {
echo $str.'<P>';
if($str == '..') $innerCounter++;
}
$oldLength = count($oldPath);
for($i=0;$i<($oldLength - $innerCounter);$i++)
$strOut .= $oldPath[$i]."/";
$newLength = count($newPath);
for($i=0;$i<$newLength;$i++){
if($newPath[$i] !='..'){
$strOut = $strOut.$newPath[$i].'';
}
}
$this->currentPath = $strOut;
return $this;
}
}
$path = new Path('/a/b/c/d');
echo $path->cd('../x')->currentPath;
@haiderktk
Copy link

haiderktk commented Jan 17, 2017

$counter = 0;
       $newLength = count($newPath);        
           for($i=0;$i<$newLength;$i++){
               if($newPath[$i] !='..'){
               	if($newPath[$i] != NULL){
               		if($counter){
                   		$strOut = $strOut."/".$newPath[$i].'';
               		} else {
                   		$strOut = $strOut.$newPath[$i].'';
               		}
               		$counter++;
               			
               	}
               	
               }
           } 

From line 25 to 30 my crapy modification but still not good for
Example case: Correct answer
Two times down: Correct answer
Three times up: Wrong answer
Complex paths: Correct answer
https://www.testdome.com/questions/php/path/7265?testId=30&testDifficulty=Hard

@rianday
Copy link

rianday commented Mar 7, 2017

I've done and passed all

you can try this one

public function cd($newPath)
    {
        $dir = explode('/', $this->currentPath);
        $cd  = explode('/', $newPath);
        $hitung = 0;
        foreach($cd as $key => $value){
            if($value == '..'){
                $hitung += 1;
                unset($cd[$key]);
            }
        }
        
        $hasil = '';
        for($i=0; $i<= (count($dir)-1-$hitung); $i++){
            $hasil .= $dir[$i].(($i == (count($dir)-1-$hitung)) ? '' : '/'); 
        }
        
        $tmp_cd = implode('/',$cd);
        $this->currentPath = $hasil.(strlen($tmp_cd)>0 ? '/'.$tmp_cd : '');

        return $this;
    }

@alexpersegona
Copy link

@rianday
First, hats off for getting 100%!

How/why does your cd function get 100% when a cd value of "/x/d" to a path of "/a/b/c/d" gives you "/a/b/c/d/x/d"? Shouldn't it be "/x/d" an absolute path? Also, your cd value excepts numbers and symbols which the notes say it shouldn't, yet you still get 100%.

All the tests I run locally work (go up dir, child, etc) but when I upload to testdome I only get 75%?

testdome.com - meh.

@rackdose
Copy link

rackdose commented Apr 16, 2018

This is working for me kinda, taking like 4 try. What a noob

public function cd($newPath)
{
    $default_directory = explode('/', $this->currentPath);
    $cd_array_path = explode('/', $newPath); 

    // count parent directory occurrence
    $tracker = $this->countParentOccurrence($cd_array_path, $default_directory);   
    
    // unset parent based on cd & get current updated path
    $cur_array_path = $this->unsetCurrentDirectory($tracker, $default_directory);
    
    // rebuilt new path
    $path = $this->rebuilt($cur_array_path);
    
    // combine updated path with targeted cd path
    $new_path = $this->newPathAfterCD($cd_array_path, $path);
    
    return $this->currentPath = $new_path;
}

public function newPathAfterCD($cd_array_path, $path)
{
    foreach ($cd_array_path as $key => $value)
    {
        if ($value != '..')
        {
            $path = $path.'/'.$value;
        }
    }
    
    return $path;
}

public function rebuilt($cur_array_path)
{
    foreach ($cur_array_path as $key => $value)
    {
        $path .= empty($value) ? '/' : $value.'/';
    }
    
    $path = rtrim($path, '/');
    
    return $path;
}

public function unsetCurrentDirectory($tracker, $default_dir)
{
    foreach ($tracker as $key => $value)
    {
        unset($default_dir[$value]);
    }
    
    return $default_dir;
}

public function countParentOccurrence($cd_array, $default_dir)
{
    $count_parent_occurence = array_count_values($cd_array);
    $dd = count($default_dir); 

    for ($i = 1; $i <= $count_parent_occurence['..']; $i++)
    {
        $cd_trail[] = $dd-$i;
    }

    return $cd_trail;
}

@najd-mrabet
Copy link

najd-mrabet commented May 15, 2018

`<?php

class Path
{
public $currentPath;

function __construct($path)
{
    $this->currentPath = $path;
}


public function cd(string $newPath)
{
    $hiearchy = explode('/', $this->currentPath);
    unset($hiearchy[0]);
    $this->checkNameDirectory($hiearchy);

    $addedHiearchy = explode('/', $newPath);
    foreach ($addedHiearchy as $value) {
        if ($value === '..') {
            array_pop($hiearchy);
        } else {
            array_push($hiearchy, $value);
        }
    }

    $this->currentPath = $this->generatePath($hiearchy);
}

public function generatePath(array $hiearchy)
{
    $path = '';
    foreach ($hiearchy as $value) {
        $path .= '/' . $value;
    }

    return $path;
}

public function checkNameDirectory(array $hiearchy)
{
    foreach ($hiearchy as $value) {
        if (preg_match('[A-Z]', $value) || preg_match('[a-z]', $value)) {
            throw new Exception('directory shiuld be a-z or A-Z');
        }
    }

}

}

$path = new Path('/a/b/c/d');
$path->cd('../x');
echo $path->currentPath;`

@mvestil
Copy link

mvestil commented Jun 22, 2018

Much shorter and simpler version without using for/foreach loop, and it Passed! :D

class Path
{
    public $currentPath;

    function __construct($path)
    {
        $this->currentPath = $path;
    }

    public function cd($newPath)
    {
	if ($this->isAbsolutePath($newPath)) {
	    $this->currentPath = $newPath;
	    return;
	}
		
        $currentPathLevelCount = substr_count($this->currentPath, '/');
        $parentLevelCount = substr_count($newPath, '..');
        
        $currentDirs = array_filter(explode('/', $this->currentPath));
	$newDirs = array_filter(explode('/', $newPath), function($value) {
		return !empty($value) && $value != '..';
	});
        
	$newPaths= array_slice($currentDirs, 0,  $parentLevelCount > $currentPathLevelCount ? 0 : $currentPathLevelCount - $parentLevelCount );
        array_push($newPaths, ...$newDirs);
        
	$this->currentPath = '/' . implode('/', $newPaths);
		
    }
    
    // For Unix
    public function isAbsolutePath($path)
    {
        return substr($path, 0, 1) == '/';
    }
}

$path = new Path('/a/b/c/d');
$path->cd('../x');
echo $path->currentPath;

@xanderZakh
Copy link

`
class Path
{
public $currentPath;

function __construct($path)
{
    $this->currentPath = $path;
}

public function cd($newPath)
{
    $dirs = explode('/', $this->currentPath);
    $new_dirs = explode('/', $newPath);
    
    $new_path = [];
    
    foreach ($new_dirs as $new_dir) {
        if ($new_dir === '..') {
            array_pop($dirs);
        } else {
            $new_path[] = $new_dir;
        }
    }
            
    $new_path = array_merge($dirs, $new_path);
    
    $this->currentPath = implode('/', $new_path);
    
}

}

$path = new Path('/a/b/c/d');
$path->cd('../x');
echo $path->currentPath;
`

@SuperStar518
Copy link

I think this might be an approved answer.

https://github.com/alidavid0418/php-path-testdome

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