I'm working through a coding challenge I found online. I have the first test case passing but failing the second. I'm trying to decide if the second test case I'm failing is a typo or not.
Here is the question:
You are given an array of desired filenames in the order of their creation. Since two files cannot have equal names, the one which es later will have an addition to its name in a form of (k), where k is the smallest positive integer such that the obtained name is not used yet.
Return an array of names that will be given to the files.
Test Cases:
1 - Passing:
- INPUT:
["doc", "doc", "image", "doc(1)", "doc"]
- OUTPUT:
["doc", "doc(1)", "image", "doc(1)(1)", "doc(2)"]
2 - Failing:
- INPUT:
["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]
- OUTPUT:
["a(1)","a(6)","a","a(2)","a(3)","a(4)","a(5)","a(7)","a(8)","a(9)","a(10)","a(11)"]
Here is my code that passes the first Spec:
function fileNaming(names) {
var finalArr = [],
obj = {};
names.forEach(function(val){
if(obj[val] === undefined){
if(finalArr.indexOf(val) === -1){
finalArr.push(val);
obj[val] = 0;
} else {
obj[val] = 1;
finalArr.push(val + "(" + obj[val] + ")" );
}
} else {
finalArr.push( val + "(" + (++obj[val]) + ")");
}
});
return finalArr;
}
Question:
- In the second test spec, why isn't there an
"a(1)(1)"
like there is a"doc(1)(1)"
Is this a typo? - If anyone has suggestions on improvining my approach or alternative approaches I would greatly appreciate your feedback.
I'm working through a coding challenge I found online. I have the first test case passing but failing the second. I'm trying to decide if the second test case I'm failing is a typo or not.
Here is the question:
You are given an array of desired filenames in the order of their creation. Since two files cannot have equal names, the one which es later will have an addition to its name in a form of (k), where k is the smallest positive integer such that the obtained name is not used yet.
Return an array of names that will be given to the files.
Test Cases:
1 - Passing:
- INPUT:
["doc", "doc", "image", "doc(1)", "doc"]
- OUTPUT:
["doc", "doc(1)", "image", "doc(1)(1)", "doc(2)"]
2 - Failing:
- INPUT:
["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]
- OUTPUT:
["a(1)","a(6)","a","a(2)","a(3)","a(4)","a(5)","a(7)","a(8)","a(9)","a(10)","a(11)"]
Here is my code that passes the first Spec:
function fileNaming(names) {
var finalArr = [],
obj = {};
names.forEach(function(val){
if(obj[val] === undefined){
if(finalArr.indexOf(val) === -1){
finalArr.push(val);
obj[val] = 0;
} else {
obj[val] = 1;
finalArr.push(val + "(" + obj[val] + ")" );
}
} else {
finalArr.push( val + "(" + (++obj[val]) + ")");
}
});
return finalArr;
}
Question:
- In the second test spec, why isn't there an
"a(1)(1)"
like there is a"doc(1)(1)"
Is this a typo? - If anyone has suggestions on improvining my approach or alternative approaches I would greatly appreciate your feedback.
-
Shouldn't it be
"a(2)"
instead of"a(1)(1)"
? – Matthew Herbst Commented Jan 24, 2016 at 3:53 -
I'm not sure, I think it should be. But if you look at the first example there is a
"doc", "doc(1)", "doc(1)(1)", "doc(2)"
. – HelloWorld Commented Jan 24, 2016 at 3:55 - The expected output looks correct. There shouldn't be a a(1)(1) because there doesn't exist a file named a(1) in the array prior to a(1) being encountered in the input. The requirement states the next minimum integer would be used if there exists a duplicate name. Since the next "a" iteration does not have a (1), it would be a(2). – Tah Commented Jan 24, 2016 at 3:56
7 Answers
Reset to default 4Here's a simpler approach. The idea is to store both the original and the generated name in the hashtable:
f = function(xs) {
var c = {}, t = (x, n) => x + "(" + n + ")";
return xs.map(function(x) {
var n = c[x] || 0;
c[x] = n + 1;
if(!n)
return x;
while(c[t(x, n)])
n++;
c[t(x, n)] = 1;
return t(x, n);
});
};
q = ["doc", "doc", "image", "doc(1)", "doc", "doc"];
document.write('<pre>'+JSON.stringify(f(q)));
q = ["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"]
document.write('<pre>'+JSON.stringify(f(q)));
Here's my approach :
def fileNaming(names):
uniq = []
for i in range(len(names)):
if names[i] not in uniq:
uniq.append(names[i])
else:
k = 1
while True:
if (names[i] + "(" + str(k) + ")") in uniq:
k += 1
else:
uniq.append(names[i] + "(" + str(k) + ")")
break
return uniq
with arrray approch
//var arr=["doc", "doc", "image", "doc(1)", "doc"];
var arr=["a(1)","a(6)","a","a","a","a","a","a","a","a","a","a"];
var arr1=new Array();
for (var r in arr)
{
if(arr1.indexOf(arr[r])>-1)
{
var ind=1;
while(arr1.indexOf(arr[r]+'('+ind+')')>-1)
{
ind++;
}
var str=arr[r]+'('+ind+')';
arr1.push(str);
}
else
{
arr1.push(arr[r]);
}
}
document.write("INPUT:"+arr+"</br>");
document.write("OUTPUT:"+arr1);
This was my beginner approach:
const renameFiles = arr => {
const fileObj = {};
let count = 0;
const renamed = arr.map(currentFile => {
if (!Object.keys(fileObj).includes(currentFile)) {
fileObj[currentFile] = count;
return currentFile;
} else {
count++;
if (Object.keys(fileObj).includes(`${currentFile}(${count})`)) {
count++;
return `${currentFile}(${count})`;
} else return `${currentFile}(${count})`;
}
});
return renamed;
};
Here is a working c++ impl.
#include <map>
#include <string>
using namespace std;
string makeName(string n, int i)
{
string ret = n + "(";
ret += std::to_string(i);
ret += ")";
return ret;
}
std::vector<std::string> fileNaming(std::vector<std::string> names)
{
map<string, int> lookup;
vector<string> outNames;
for (auto name : names)
{
auto f = lookup.find(name);
if (f != lookup.end())
{
int index = 1;
while (lookup.find(makeName(name, index)) != lookup.end())
{
index++;
}
name = makeName(name, index); // reassign
}
lookup[name] = 1;
outNames.push_back(name);
}
return outNames;
}
JAVA version based on the accepted answer:
String[] solution(String[] names) {
Map<String, Integer> countMap = new HashMap<>();
String[] result = new String[names.length];
for (int i = 0; i < names.length; i++) {
int count = countMap.getOrDefault(names[i], 0);
countMap.put(names[i], count + 1);
if (count == 0) {
result[i] = names[i];
} else {
while (countMap.containsKey(names[i] + "(" + count + ")"))
count++;
countMap.put(names[i] + "(" + count + ")", 1);
result[i] = names[i] + "(" + count + ")";
}
}
return result;
}
Here is my approach in Javascript:
function fileNaming(names) {
for (i in names) {
if (names.slice(0,i).includes(names[i])) {
j = 1
while (names.slice(0,i).includes(names[i]+"("+j.toString()+")")) {j++}
names[i] += "(" + j.toString() + ")"}}
return names
}