Uniquify Identifiers


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
2560

2
@ Adámไม่ควร6, 6, ...ให้6, 1, ...?
xnor

5
@ Adam ฉันคิดว่าคุณถูกต้องเกี่ยวกับสิ่งนั้น แต่ถ้อยคำอาจชัดเจนยิ่งขึ้น "ตั้งค่า" หมายถึงองค์ประกอบที่พบองค์ประกอบทั้งหมดของรายการที่นำเข้าหรือองค์ประกอบในรายการตามที่มันยืนอยู่ตอนนี้หรือไม่
xnor

3
@xnor 6, 6, 4, 4, 2, 2กรณีทดสอบยืนยันการตีความของอาดัม: การส่งออกที่คาดว่าจะเป็นและไม่6, 1, 4, 3, 2, 5 6, 1, 4, 2, 3, 5
เสียชีวิต

2
0 นับเป็นจำนวนเต็มบวกสำหรับความท้าทายนี้หรือไม่?
ลุ

คำตอบ:



8

Java 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

ทับทิม , 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

05AB1E , 17 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

ฉันควรจะใช้การลดแทนแผนที่ ... ให้ฉันดูว่าช่วยได้ไหม
Leaky Nun

@LeakyNun: ลดหรือแผนที่มักจะมีวิธีที่จะไป :)
Emigna


3
[6, '1', '2', '3', '4', '5', '7']จะช่วยให้ [6, '7', '1', '2', '3', '4', '5']ควรให้
Adám

1
@ Adám: ขอบคุณสำหรับการจับ! แก้ไขแล้วตอนนี้ :)
Emigna

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ยังไม่ได้ถูกนำมาใช้แล้ว, jเอาท์พุทเป็นอย่างอื่น สุดท้ายให้อัปเดตjทุกครั้งที่คุณส่งออกบางสิ่ง

แก้ไข: [6, 6, 4, 4, 2, 2]การแก้ไขปัญหาการป้อนข้อมูลผิดพลาดของการจัดการ ขอบคุณ @Rod ที่ชี้ให้เห็นข้อผิดพลาดและการแก้ไข ข้อผิดพลาดคือในกรณีของรายการที่ซ้ำกันมันจะส่งออกจำนวนน้อยที่สุดที่ไม่ได้ใช้ไปยังจุดนั้นในรายการแม้ว่าผลลัพธ์นั้นจะปรากฏในภายหลังในอินพุต (นี่เป็นความผิดตามที่อธิบายไว้ในโพสต์และความคิดเห็น แต่ฉันก็ยังสับสนอยู่ดี) อย่างไรก็ตามการแก้ไขคือการเพิ่มรายการอินพุตเพียงอย่างaเดียวไปยังชุดของค่าที่ไม่สามารถแสดงผลได้ในกรณีนั้น


ไม่ได้ผล[6,6,4,4,2,2]คุณสามารถ (อาจ) แก้ไขได้โดยเพิ่ม+aลงในwhile j in u:->while j in u+a:
Rod

@ เร็วคุณพูดถูกความผิดของฉัน (อย่างใดฉันยังคงสับสนนี้แม้จะมีความคิดเห็นเกี่ยวกับเรื่องนี้ - ขอบคุณที่นำมาให้ความสนใจของฉัน - และฉันยังไม่ได้ทดสอบวิธีการแก้ปัญหาของฉันได้ดีพอกับกรณีทดสอบน่าอาย) ตกลงฉันได้รวมที่ดีมากของคุณ แก้ไขและตรวจสอบกับกรณีทดสอบ ขอบคุณ!
mathmandan

5

Haskell , 79 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 เป็นรายการที่ว่างเปล่าเนื่องจากรายการที่ไม่ได้รับการจัดการได้ถูกจัดการในบรรทัดก่อนหน้า
  • ฟังก์ชั่นหลัก([]#)รับรายการและเรียก#มันเป็นอาร์กิวเมนต์ที่สองและรายการว่างสำหรับอาร์กิวเมนต์แรก

|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;};

Ungolfed

( 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();
      }
   }
}

ข่าว

  • v1.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 ไบต์

input = array a, output = modified 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มีอยู่ในรายการผลลัพธ์เราจะนำองค์ประกอบที่ 2 (1 เมื่อดัชนี 0) จากรายการจำนวนเต็ม(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)

ungolf และผลลัพธ์

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.