统一标识符


31

介绍

根据定义,唯一标识符应该是唯一的。具有多个相同的标识符会导致检索意外数据。但是,由于数据是同时从多个来源到达的,因此很难确保唯一性。编写一个函数以统一标识符列表。

这可能是我写的最糟糕的拼图绒毛,但您明白了。

要求

给定一个零个或多个正整数的列表,请对每个数字从头到尾应用以下规则:

  • 如果数字是同类数字中的第一个,请保留该数字。
  • 如果以前遇到过该数字,请用在整个输入列表或任何现有输出中未找到的最低正整数替换它。

对于解决方案:

  • 解决方案可以是程序或功能。
  • 输入可以是字符串,数组,作为参数传递的输入或键盘输入。
  • 输出可以是字符串,数组或打印到屏幕上。
  • 输出列表中的所有数字都是唯一的。

假设条件

  • 输入列表是干净的。它仅包含正整数。
  • 正整数的范围是1到2 31 -1。
  • 程序变量的可用内存少于256 MB。(基本上,不允许使用2,147,483,648个元素的数组。)

测试用例

Input:  empty
Output: empty

Input:  5
Output: 5

Input:  1, 4, 2, 5, 3, 6
Output: 1, 4, 2, 5, 3, 6

Input:  3, 3, 3, 3, 3, 3
Output: 3, 1, 2, 4, 5, 6

Input:  6, 6, 4, 4, 2, 2
Output: 6, 1, 4, 3, 2, 5

Input:  2147483647, 2, 2147483647, 2
Output: 2147483647, 2, 1, 3

计分

只是一个简单的代码高尔夫。下周这个时间的最低字节数将获胜。


4
添加测试用例:6, 6, 1, 2, 3, 4, 56, 7, 1, 2, 3, 4, 5
亚当

2
@Adám不应该6, 6, ...6, 1, ...吗?
xnor

5
@Adám我认为您是对的,但措辞可能更清楚,“设置”是指遇到的元素,输入列表的所有元素还是列表中的当前元素?
xnor

3
@xnor 6, 6, 4, 4, 2, 2测试用例证实了Adám的解释:预期的输出是6, 1, 4, 3, 2, 5,而不是6, 1, 4, 2, 3, 5
Fatalize'5

2
0算作此挑战的正整数吗?
路加福音

Answers:


11

Brachylog,8个字节

{|∧ℕ₁}ᵐ≠

在线尝试!

说明

{    }ᵐ     Map on the Input:
              Input = Output…
 |            …or…
  ∧ℕ₁         …Output is in [1,+inf)
       ≠    All elements of the output must be different
            (Implicit labeling)

8

爪哇8,158个 144字节

a->{int m=0;String r="",c=",",b=r;for(int x:a)b+=x+c;for(int x:a)if(r.contains(x+c)){for(;(r+b).contains(++m+c););r+=m+c;}else r+=x+c;return r;}
  • .contains(m+c);m++).contains(++m+c);)保存1个字节,并且同时转换为Java 8保存13多个字节。

说明:

在这里尝试。

a->{                      // Method with integer-array parameter and String return-type
  int m=0;                //  Lowest integer
  String r="",            //  Result-String
         c=",",           //  Comma delimiter for result String
         b=r;for(int x:a)b+=x+c;
                          //  Input array as String
  for(int x:a)            //  Loop (2) over the integers in the array
    if(r.contains(x+c)){  //   If the result already contains this integer
      for(;(r+b).contains(++m+c););
                          //    Inner (3) as long as either the result-String or array-String contains the lowest integer
                          //     and raise the lowest integer before every iteration by 1
      r+=m+c;             //    Append the result with this lowest not-present integer
    }else                 //   Else:
      r+=x+c;             //    Append the result-String with the current integer
                          //  End of loop (2) (implicit / single-line body)
  return r;               //  Return the result-String
}                         // End of method

7

JavaScript(ES6),49个字节

a=>a.map(g=(e,i)=>a.indexOf(e)-i?g(++n,-1):e,n=0)

7

红宝石,63字节

->a{r=*0..a.size;r.map{|i|[a[i]]-a[0,i]==[]?a[i]=(r-a)[1]:0};a}

在线尝试!

说明

->a{                                    # Anonymous function with one argument
    r=*0..a.size;                       # Numbers from 0 to array size
    r.map{|i|                           # For all numbers in range:
        [a[i]]                          #  Get array with just a[i]
              -a[0,i]                   #  Remove elements from array that are
                                        #    also in a[0..i-1]
                    ==[]?               #  Check if result is an empty array
                        a[i]=           #  If true, set a[i] to:
                             (r-a)      #   Remove elements from number range
                                        #     that are also in input array
                                  [1]   #   Get second element (first non-zero)
                        :0};            #  If false, no-op
                            a}          # Return modified array

6

05AB1E17 16 18字节

vy¯yåi¹gL¯K¹K¬}ˆ}¯

在线尝试!

说明

v                    # for each y in input
 y                   # push y
  ¯yåi               # if y exist in global list
      ¹gL            # push [1 ... len(input)]
         ¯K          # remove any number that is already in global list
           ¹K        # remove any number that is in the input
             ¬       # get the first (smallest)
              }      # end if
               ˆ     # add to global list
                }¯   # end loop, push and output global list

我可能应该使用reduce而不是map ...让我看看是否有帮助
Leaky Nun

@LeakyNun:缩小或绘制地图通常是一种方法:)
Emigna


3
[6, '1', '2', '3', '4', '5', '7']。应该给[6, '7', '1', '2', '3', '4', '5']
阿达姆(Adám)'17年

1
@Adám:谢谢你的帮助!现在修复:)
艾米娜(Emigna)'17

6

PHP,121字节

<?$n=array_diff(range(0,count($g=$_GET)),$g);sort($n);$r=[];foreach($g as$v)$r[]=in_array($v,$r)?$n[++$i]:$v;print_r($r);

在线版本

展开式

$n=array_diff(range(0,count($g=$_GET)),$g); # create array of ascending values which are not in input array plus zero
sort($n); # minimize keys
$r=[];  # empty result array
foreach($g as$v) # loop input array
  $r[]=in_array($v,$r)?$n[++$i]:$v; # if value is not in result array add value else take new unique value skip zero through ++$i
print_r($r); # output result array

5

Python 2,77 79字节

a=input();u=[];j=1
for x in a:
 u+=[[x,j][x in u]]
 while j in u+a:j+=1
print u

接受键盘输入,例如[3, 3, 3, 3, 3, 3]

只需跟踪j到目前为止尚未使用的最小正整数即可。对于x输入的每个元素,x如果x尚未使用output,则为output j。最后,j每次输出内容时进行更新。

编辑:修复输入的错误处理[6, 6, 4, 4, 2, 2]。感谢@Rod指出错误以及解决方法。错误是,如果输入重复,它将输出列表中该点未使用的最小数字,即使该输出稍后出现在输入中。(这是错误的,正如文章和评论中所阐明的那样,但我仍然以某种方式弄乱了。)无论如何,解决方法是将输入列表添加a到在这种情况下无法输出的值集。


不适用于[6,6,4,4,2,2]您,您可以(可能)通过将它添加+awhile j in u:->while j in u+a:
Rod

@Rod你是对的,我的错。(尽管有这样的评论,我还是还是弄糟了-感谢您引起我的注意-并且我也没有针对测试案例对我的解决方案进行足够好的测试。令人尴尬。)好吧,我已经把您的很好修复并针对测试用例进行验证。谢谢!
mathmandan

5

Haskell79 76字节

编辑:

  • -3个字节:@nimi看到head可以用模式匹配代替。

([]#)是获取并返回列表的匿名函数。使用([]#)[2147483647, 2, 2147483647, 2]

(?)=notElem
s#(x:y)|z:_<-[x|x?s]++filter(?(s++y))[1..]=z:(z:s)#y
_#n=n
([]#)

在线尝试!

怎么运行的

  • ? 是用于检查列表中是否缺少元素的缩写运算符。
  • s#l处理整数列表l给出一个列表,s已经使用的整数。
    • x是要查看的下一个整数,y其余为整数。
    • z是为下一个位置选择的整数。这x如果x不是的元素s,和第一正整数既不s也不y除外。
    • (z:s)#y然后递归并z添加到使用的整数列表中。
    • n 是一个空列表,因为非空列表已在上一行中处理过。
  • main函数([]#)接受一个列表,并将#其作为第二个参数调用,并为第一个参数添加一个空列表。

|z:_<-[x|...]...
nimi



3

C#,135字节


打高尔夫球

(int[] i)=>{for(int x=1,v,m=0,l=i.Length,y;x<l;x++){v=i[x];for(y=0;y<l&&v==i[x]?y<x:y<l;y++)if(i[y]==v){v=++m;y=-1;}i[x]=v;}return i;};

不打高尔夫球

( int[] i ) => {
   for( int x = 1, v, m = 0, l = i.Length, y; x < l; x++ ) {
      v = i[ x ];

      for( y = 0; y < l && v == i[ x ] ? y < x : y < l ; y++ )
         if( i[ y ] == v ) {
            v = ++m;
            y = -1;
         }

      i[ x ] = v;
   }

   return i;
};

非高尔夫可读

// Takes an array of Int32 objects ( 32-byte signed integers )
( int[] i ) => {

   // Cycles through each element on the array
   //   x: Scan position, starts at the 2nd element
   //   v: Value being processed
   //   m: The next minimum value to replace
   //   l: Size of the array, to save some byte count
   for( int x = 1, v, m = 0, l = i.Length, y; x < l; x++ ) {

      // Hold the value
      v = i[ x ];

      // Re-scan the array for a duplicate value up the the current position ( 'x' ) IF
      //   ... the currently hold value hasn't been modified
      //   ... otherwise, re-scans the entire array to find a suitable value to replace
      for( y = 0; y < l && v == i[ x ] ? y < x : y < l ; y++ )

         // Check if 'v' shares the same value with other element
         if( i[ y ] == v ) {

            // Set 'v' to the minimum value possible
            v = ++m;

            // Reset the scan position to validate the new value
            y = -1;
         }

      // Set the 'v' to the array
      i[ x ] = v;
   }

   // Return the array
   return i;
};

完整代码

using System;
using System.Collections.Generic;

namespace Namespace {
   class Program {
      static void Main( String[] args ) {
         Func<Int32[], Int32[]> f = ( int[] i ) => {
            for( int x = 1, v, m = 0, l = i.Length, y; x < l; x++ ) {
               v = i[ x ];

               for( y = 0; y < l && v == i[ x ] ? y < x : y < l ; y++ )
                  if( i[ y ] == v ) {
                     v = ++m;
                     y = -1;
                  }

               i[ x ] = v;
            }

            return i;
         };

         List<Int32[]>
            testCases = new List<Int32[]>() {
               new Int32[] { },
               new Int32[] { 5 },
               new Int32[] { 1, 4, 2, 5, 3, 6 },
               new Int32[] { 3, 3, 3, 3, 3, 3 },
               new Int32[] { 6, 6, 4, 4, 2, 2 },
               new Int32[] { 2147483647, 2, 2147483647, 2 },
            };

         foreach( Int32[] testCase in testCases ) {
            Console.WriteLine( $" Input: {String.Join( ",", testCase )}\nOutput: {string.Join( ",", f( testCase ) )}\n" );
         }

         Console.ReadLine();
      }
   }
}

发布

  • 1.0 - 135 bytes-初始溶液。

笔记

  • 没有


3

R,39 46字节

从输入创建向量,然后将重复的值替换为从1到一百万的范围,其中输入值已删除。返回数值向量。没有输入将返回空矢量数字(0)。

i[duplicated(i)]=(1:1e6)[-(i=scan())];i

在线尝试!

这将引发有关替换向量长度的警告

                           i=scan()     # set i as input
                 (1:1e6)                # 1 to a million (could go higher)
                 (1:1e6)[-(i=scan())]   # without input values
  duplicated(i)                         # duplicate values in i
i[duplicated(i)]=(1:1e6)[-(i=scan())]   # set duplicate i values to reduced range vector
                                     ;i # return result

3

C,169字节 133字节

输入=数组a,输出=修改后的数组a

i=1,j,k,l;void f(int*a,int n){for(;i<n;i++)for(j=i-1;j>=0;j--)if(a[i]==a[j]){l=1;for(k=0;k<n;)if(l==a[k])k=l++?0:0;else k++;a[i]=l;}}

格式化的

int i, j, k, l;
void f(int* a, int n)
{
    for (i = 1; i<n; i++)
        for (j = i - 1; j >= 0; j--)
            if (a[i] == a[j])
            {
                l = 1;
                for (k = 0; k<n;)
                    if (l == a[k])
                        k = l++ ? 0 : 0;
                    else
                        k++;
                a[i] = l;
            }
}

这些循环浪费了太多字节。是否有人想到通过发明新算法(使用更少的循环)来缩短代码?我在想,但还没有找到。


2

C#7,116字节

int[]f(int[]c){int j=0;int h()=>c.Contains(++j)?h():j;return c.Select((e,i)=>Array.IndexOf(c,e)<i?h():e).ToArray();}

缩进

int[] f(int[] c)
{
    int j = 0;
    int h() => c.Contains(++j) ? h() : j;
    return c
        .Select((e, i) => Array.IndexOf(c, e) < i ? h() : e)
        .ToArray();
}

讲解

  • 第一次出现数字始终保持原样
  • 从中提取连续出现的数字[1, 2, 3, ...],跳过输入中存在的值。

在线版本


2

Clojure,72个字节

#(reduce(fn[r i](conj r(if((set r)i)(nth(remove(set r)(range))1)i)))[]%)

基本减少。i到目前为止,如果if 包含在输出列表中,我们将从无限的整数列表中获取第二个元素(0索引时为1)(range),从中我们删除了已经使用的那些数字。范围从零开始,因此我们不能取第一个元素,而取第二个元素。


1

R,74个字节

从stdin读取列表;对于空输入返回NULL。

o=c();for(i in n<-scan())o=c(o,`if`(i%in%o,setdiff(1:length(n),o)[1],i));o

说明:

o=c()                                #initialize empty list of outputs
for(i in n<-scan())                  # loop through the list after reading it from stdin
    o=c(o,                           # set the output to be the concatenation of o and
      `if`(i%in%o,                   # if we've seen the element before
           setdiff(1:length(n),o)[1] # the first element not in 1,2,...
           ,i))                      # otherwise the element
o                                    # print the output

1:length(n) 可以使用,因为我们保证永远都不需要该范围之外的替代品。

在线尝试!


0

公理,169字节

f a==(r:List INT:=[];for i in 1..#a repeat(~member?(a.i,r)=>(r:=concat(r,a.i));for j in 1..repeat if~member?(j,r)and(~member?(j,a)or j=a.i)then(r:=concat(r,j);break));r)

高低不平和结果

ff(a)==
  r:List INT:=[]
  for i in 1..#a repeat
      ~member?(a.i,r)=>(r:=concat(r,a.i))
      for j in 1.. repeat
            if~member?(j,r)and(~member?(j,a) or j=a.i)then(r:=concat(r,j);break)
  r

(3) -> f([])
   (3)  []
                                                       Type: List Integer
(4) -> f([5])
   (4)  [5]
                                                       Type: List Integer
(5) -> f([1,4,2,5,3,6])
   (5)  [1,4,2,5,3,6]
                                                       Type: List Integer
(6) -> f([3,3,3,3,3,3])
   (6)  [3,1,2,4,5,6]
                                                       Type: List Integer
(7) -> f([6, 6, 4, 4, 2, 2])
   (7)  [6,1,4,3,2,5]
                                                       Type: List Integer
(8) -> f([2147483647, 2, 2147483647, 2])
   (8)  [2147483647,2,1,3]
                                                       Type: List Integer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.